diff --git a/.gitmodules b/.gitmodules index 32ff019b..139613cf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,21 +1,21 @@ -[submodule "ros/opentera-webrtc-ros"] - path = ros/opentera-webrtc-ros - url = https://github.com/introlab/opentera-webrtc-ros.git +[submodule "system/optional"] + path = system/optional + url = https://github.com/TartanLlama/optional.git +[submodule "ros/utils/hbba_lite"] + path = ros/utils/hbba_lite + url = https://github.com/introlab/hbba_lite.git +[submodule "ros/utils/audio_utils"] + path = ros/utils/audio_utils + url = https://github.com/introlab/audio_utils.git [submodule "ros/perceptions/odas_ros"] path = ros/perceptions/odas_ros url = https://github.com/introlab/odas_ros.git -[submodule "ros/utils/recorders/3rd_party/SQLiteCpp"] - path = ros/utils/recorders/3rd_party/SQLiteCpp - url = https://github.com/SRombauts/SQLiteCpp.git [submodule "ros/demos/home_logger/3rd_party/fmt"] path = ros/demos/home_logger/3rd_party/fmt url = https://github.com/fmtlib/fmt.git -[submodule "ros/utils/audio_utils"] - path = ros/utils/audio_utils - url = https://github.com/introlab/audio_utils.git -[submodule "ros/utils/hbba_lite"] - path = ros/utils/hbba_lite - url = https://github.com/introlab/hbba_lite.git -[submodule "system/optional"] - path = system/optional - url = https://github.com/TartanLlama/optional.git +[submodule "ros/utils/recorders/3rd_party/SQLiteCpp"] + path = ros/utils/recorders/3rd_party/SQLiteCpp + url = https://github.com/SRombauts/SQLiteCpp.git +[submodule "ros/utils/opentera-webrtc-ros"] + path = ros/utils/opentera-webrtc-ros + url = https://github.com/introlab/opentera-webrtc-ros.git diff --git a/documentation/assembly/01_COMPUTER_CONFIGURATION.md b/documentation/assembly/01_COMPUTER_CONFIGURATION.md index b9dd8f02..b2786f2e 100644 --- a/documentation/assembly/01_COMPUTER_CONFIGURATION.md +++ b/documentation/assembly/01_COMPUTER_CONFIGURATION.md @@ -712,3 +712,12 @@ export GOOGLE_APPLICATION_CREDENTIALS="[Path to the service account JSON keyfile ```bash export OPEN_WEATHER_MAP_API_KEY="[The key]" ``` + +### C. Setup a Different ROS2 Domain on Each Robot + +1. Add the following line to `~/.bashrc` + +```bash +# Avoid default=0 and make sure each robot has a different domain ID. +export ROS_DOMAIN_ID=[1...101] +``` diff --git a/documentation/assembly/13_CALIBRATION.md b/documentation/assembly/13_CALIBRATION.md index da6b359b..9f713475 100644 --- a/documentation/assembly/13_CALIBRATION.md +++ b/documentation/assembly/13_CALIBRATION.md @@ -4,11 +4,13 @@ 1. Execute the following command. ```bash -roslaunch t_top platform.launch camera_2d_wide_enabled:=true +ros2 launch t_top platform.launch.xml camera_2d_wide_enabled:=true ``` 2. Follow the following [steps](http://wiki.ros.org/camera_calibration/Tutorials/MonocularCalibration). ```bash -rosrun camera_calibration cameracalibrator.py --size 8x6 --square 0.69 image:=/camera_2d_wide_full_hd/image camera:=/camera_2d_wide_full_hd +# Create calibration path +mkdir -p ~/.ros/t-top/calibration +ros2 run camera_calibration cameracalibrator --size 9x6 --square 0.051 --ros-args -r image:=/camera_2d_wide_full_hd/image -r camera/set_camera_info:=/camera_2d_wide_full_hd/set_camera_info ``` ## B. sound_object_person_following @@ -16,5 +18,5 @@ rosrun camera_calibration cameracalibrator.py --size 8x6 --square 0.69 image:=/c 1. Place an object having visual features in front of the robot. 2. Execute the following command. ```bash -roslaunch sound_object_person_following calibrate_sound_object_person_following.launch +ros2 launch sound_object_person_following calibrate_sound_object_person_following.launch.xml ``` diff --git a/ros/.gitignore b/ros/.gitignore deleted file mode 100644 index 0c03be98..00000000 --- a/ros/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.idea/ -venv -__pycache__ diff --git a/ros/behaviors/behavior_msgs/CMakeLists.txt b/ros/behaviors/behavior_msgs/CMakeLists.txt new file mode 100644 index 00000000..35804804 --- /dev/null +++ b/ros/behaviors/behavior_msgs/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 3.5) +project(behavior_msgs) + + +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(daemon_ros_client REQUIRED) +find_package(rosidl_default_generators REQUIRED) + +# Generate messages +rosidl_generate_interfaces(${PROJECT_NAME} + "msg/Done.msg" + "msg/GestureName.msg" + "msg/LedAnimation.msg" + "msg/SoundFile.msg" + "msg/SoundStarted.msg" + "msg/Statistics.msg" + "msg/Text.msg" + DEPENDENCIES daemon_ros_client +) + +ament_package() diff --git a/ros/behaviors/gesture/msg/Done.msg b/ros/behaviors/behavior_msgs/msg/Done.msg similarity index 100% rename from ros/behaviors/gesture/msg/Done.msg rename to ros/behaviors/behavior_msgs/msg/Done.msg diff --git a/ros/behaviors/gesture/msg/GestureName.msg b/ros/behaviors/behavior_msgs/msg/GestureName.msg similarity index 100% rename from ros/behaviors/gesture/msg/GestureName.msg rename to ros/behaviors/behavior_msgs/msg/GestureName.msg diff --git a/ros/behaviors/led_animations/msg/Animation.msg b/ros/behaviors/behavior_msgs/msg/LedAnimation.msg similarity index 100% rename from ros/behaviors/led_animations/msg/Animation.msg rename to ros/behaviors/behavior_msgs/msg/LedAnimation.msg diff --git a/ros/behaviors/sound_player/msg/SoundFile.msg b/ros/behaviors/behavior_msgs/msg/SoundFile.msg similarity index 100% rename from ros/behaviors/sound_player/msg/SoundFile.msg rename to ros/behaviors/behavior_msgs/msg/SoundFile.msg diff --git a/ros/behaviors/sound_player/msg/Started.msg b/ros/behaviors/behavior_msgs/msg/SoundStarted.msg similarity index 100% rename from ros/behaviors/sound_player/msg/Started.msg rename to ros/behaviors/behavior_msgs/msg/SoundStarted.msg diff --git a/ros/behaviors/talk/msg/Statistics.msg b/ros/behaviors/behavior_msgs/msg/Statistics.msg similarity index 100% rename from ros/behaviors/talk/msg/Statistics.msg rename to ros/behaviors/behavior_msgs/msg/Statistics.msg diff --git a/ros/behaviors/talk/msg/Text.msg b/ros/behaviors/behavior_msgs/msg/Text.msg similarity index 100% rename from ros/behaviors/talk/msg/Text.msg rename to ros/behaviors/behavior_msgs/msg/Text.msg diff --git a/ros/behaviors/behavior_msgs/package.xml b/ros/behaviors/behavior_msgs/package.xml new file mode 100644 index 00000000..278c7707 --- /dev/null +++ b/ros/behaviors/behavior_msgs/package.xml @@ -0,0 +1,24 @@ + + + + behavior_msgs + 0.0.0 + The behavior_msgs package + Marc-Antoine Maheux + GPL-3.0 license + + ament_cmake + rosidl_default_generators + + daemon_ros_client + + rosidl_default_runtime + rosidl_interface_packages + + ament_lint_auto + ament_lint_common + + + ament_cmake + + diff --git a/ros/behaviors/behavior_srvs/CMakeLists.txt b/ros/behaviors/behavior_srvs/CMakeLists.txt new file mode 100644 index 00000000..b4b467bc --- /dev/null +++ b/ros/behaviors/behavior_srvs/CMakeLists.txt @@ -0,0 +1,28 @@ +cmake_minimum_required(VERSION 3.5) +project(behavior_srvs) + + +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rosidl_default_generators REQUIRED) + +# Generate services +rosidl_generate_interfaces(${PROJECT_NAME} + "srv/GenerateSpeechFromText.srv" +) + +ament_package() diff --git a/ros/behaviors/behavior_srvs/package.xml b/ros/behaviors/behavior_srvs/package.xml new file mode 100644 index 00000000..5fe53c23 --- /dev/null +++ b/ros/behaviors/behavior_srvs/package.xml @@ -0,0 +1,22 @@ + + + + behavior_srvs + 0.0.0 + The behavior_srvs package + Marc-Antoine Maheux + GPL-3.0 license + + ament_cmake + rosidl_default_generators + + rosidl_default_runtime + rosidl_interface_packages + + ament_lint_auto + ament_lint_common + + + ament_cmake + + diff --git a/ros/behaviors/piper_ros/srv/GenerateSpeechFromText.srv b/ros/behaviors/behavior_srvs/srv/GenerateSpeechFromText.srv similarity index 100% rename from ros/behaviors/piper_ros/srv/GenerateSpeechFromText.srv rename to ros/behaviors/behavior_srvs/srv/GenerateSpeechFromText.srv diff --git a/ros/behaviors/dance/CMakeLists.txt b/ros/behaviors/dance/CMakeLists.txt index 6fbe000e..83246a06 100644 --- a/ros/behaviors/dance/CMakeLists.txt +++ b/ros/behaviors/dance/CMakeLists.txt @@ -1,221 +1,43 @@ -cmake_minimum_required(VERSION 2.8.3) - -if (POLICY CMP0048) - cmake_policy(SET CMP0048 NEW) -endif (POLICY CMP0048) - +cmake_minimum_required(VERSION 3.5) project(dance) -## Compile as C++11, supported in ROS Kinetic and newer -add_compile_options(-std=c++11) - -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - rospy - roscpp - std_msgs - hbba_lite - t_top - daemon_ros_client - ) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -# add_message_files( -# FILES -# Message1.msg -# Message2.msg -# ) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -# generate_messages( -# DEPENDENCIES -# std_msgs -# ) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( - # INCLUDE_DIRS include - # LIBRARIES dance - CATKIN_DEPENDS rospy roscpp std_msgs - # DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( - # include - ${catkin_INCLUDE_DIRS} +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclpy REQUIRED) +find_package(daemon_ros_client REQUIRED) +find_package(std_msgs REQUIRED) +find_package(hbba_lite REQUIRED) +find_package(t_top REQUIRED) + +# Python Librairies +ament_python_install_package(${PROJECT_NAME}) + +# Python Nodes +install(PROGRAMS + scripts/head_dance_node.py + scripts/led_dance_node.py + scripts/torso_dance_node.py + DESTINATION lib/${PROJECT_NAME} ) -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/dance.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -# add_executable(${PROJECT_NAME}_node src/audio_utils_node.cpp) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -# target_link_libraries(beat_detector_node -# ${catkin_LIBRARIES} -# ) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -catkin_install_python(PROGRAMS - scripts/head_dance_node.py - scripts/torso_dance_node.py - scripts/led_dance_node.py - DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -) - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -# install(PROGRAMS -# scripts/my_python_script -# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# +# Install the movements files +install(DIRECTORY movements DESTINATION share/${PROJECT_NAME}) -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_dance.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() +# Launch files +install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}) -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/behaviors/dance/README.md b/ros/behaviors/dance/README.md index 3e671ee1..d5ec8661 100644 --- a/ros/behaviors/dance/README.md +++ b/ros/behaviors/dance/README.md @@ -14,19 +14,19 @@ This node makes T-Top head dance on the beat. The moves are randomly chosen. #### Subscribed Topics -- `bpm` ([std_msgs/Float32](http://docs.ros.org/en/noetic/api/std_msgs/html/msg/Float32.html)): The bpm topic from the +- `bpm` ([std_msgs/Float32](https://docs.ros.org/en/humble/p/std_msgs/interfaces/msg/Float32.html)): The bpm topic from the beat_detector_node. -- `beat` ([std_msgs/Bool](http://docs.ros.org/en/noetic/api/std_msgs/html/msg/Bool.html)): The beat topic from the +- `beat` ([std_msgs/Bool](https://docs.ros.org/en/humble/p/std_msgs/interfaces/msg/Bool.html)): The beat topic from the beat_detector_node. #### Published Topics -- `dance/set_head_pose` ([geometry_msgs/PoseStamped](http://docs.ros.org/en/noetic/api/geometry_msgs/html/msg/PoseStamped.html)): +- `dance/set_head_pose` ([geometry_msgs/PoseStamped](https://docs.ros.org/en/humble/p/geometry_msgs/interfaces/msg/PoseStamped.html)): The head pose. #### Services -- `pose/filter_state` ([hbba_lite/SetOnOffFilterState](../../hbba_lite/srv/SetOnOffFilterState.srv)): The HBBA filter +- `pose/filter_state` ([hbba_lite_srvs/SetOnOffFilterState](../../hbba_lite/hbba_lite_srvs/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the behavior. @@ -40,20 +40,20 @@ This node makes T-Top torso dance on the beat. The moves are randomly chosen. #### Subscribed Topics -- `bpm` ([std_msgs/Float32](http://docs.ros.org/en/noetic/api/std_msgs/html/msg/Float32.html)): The bpm topic from the +- `bpm` ([std_msgs/Float32](https://docs.ros.org/en/humble/p/std_msgs/interfaces/msg/Float32.html)): The bpm topic from the beat_detector_node. -- `beat` ([std_msgs/Bool](http://docs.ros.org/en/noetic/api/std_msgs/html/msg/Bool.html)): The beat topic from the +- `beat` ([std_msgs/Bool](https://docs.ros.org/en/humble/p/std_msgs/interfaces/msg/Bool.html)): The beat topic from the beat_detector_node. - `daemon/motor_status` ([daemon_ros_client/MotorStatus](../../daemon_ros_client/msg/MotorStatus.msg)): The motor status to get torso orientation. #### Published Topics -- `dance/set_torso_orientation` ([std_msgs/Float32](http://docs.ros.org/en/noetic/api/std_msgs/html/msg/Float32.html)): The +- `dance/set_torso_orientation` ([std_msgs/Float32](https://docs.ros.org/en/humble/p/std_msgs/interfaces/msg/Float32.html)): The torso orientation. #### Services -- `pose/filter_state` ([hbba_lite/SetOnOffFilterState](../../hbba_lite/srv/SetOnOffFilterState.srv)): The HBBA filter +- `pose/filter_state` ([hbba_lite_srvs/SetOnOffFilterState](../../utils/hbba_lite/hbba_lite_srvs/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the behavior. @@ -67,7 +67,7 @@ This node makes T-Top torso dance on the beat. The moves are randomly chosen. #### Subscribed Topics -- `beat` ([std_msgs/Bool](http://docs.ros.org/en/noetic/api/std_msgs/html/msg/Bool.html)): The beat topic from the +- `beat` ([std_msgs/Bool](https://docs.ros.org/en/humble/p/std_msgs/interfaces/msg/Bool.html)): The beat topic from the beat_detector_node. #### Published Topics @@ -77,5 +77,5 @@ This node makes T-Top torso dance on the beat. The moves are randomly chosen. #### Services -- `set_led_colors/filter_state` ([hbba_lite/SetOnOffFilterState](../../hbba_lite/srv/SetOnOffFilterState.srv)): The HBBA filter +- `set_led_colors/filter_state` ([hbba_lite_srvs/SetOnOffFilterState](../../utils/hbba_lite/hbba_lite_srvs/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the behavior. diff --git a/ros/behaviors/face_following/src/face_following/__init__.py b/ros/behaviors/dance/dance/__init__.py similarity index 100% rename from ros/behaviors/face_following/src/face_following/__init__.py rename to ros/behaviors/dance/dance/__init__.py diff --git a/ros/behaviors/dance/src/dance/lib_pose_dance_node.py b/ros/behaviors/dance/dance/lib_pose_dance_node.py similarity index 51% rename from ros/behaviors/dance/src/dance/lib_pose_dance_node.py rename to ros/behaviors/dance/dance/lib_pose_dance_node.py index b06b09b5..c8a4985e 100755 --- a/ros/behaviors/dance/src/dance/lib_pose_dance_node.py +++ b/ros/behaviors/dance/dance/lib_pose_dance_node.py @@ -1,11 +1,13 @@ #!/usr/bin/env python3 from abc import ABC, abstractmethod -import threading import json import random -import rospy +import rclpy +import rclpy.node +from rclpy.duration import Duration + from std_msgs.msg import Float32 from std_msgs.msg import Bool @@ -15,39 +17,38 @@ P_CHANGE_MOVEMENT = 0.25 -class PoseDanceNode(ABC): - def __init__(self): - self._lock = threading.Lock() +class PoseDanceNode(rclpy.node.Node, ABC): + def __init__(self, node_name): + super(PoseDanceNode, self).__init__(node_name) - with open(rospy.get_param('~movement_file'), 'r') as f: + movement_file = self.declare_parameter('movement_file', '').get_parameter_value().string_value + with open(movement_file, 'r') as f: self._movements = json.load(f) self._current_movement = self._movements[list(self._movements.keys())[0]] self._current_movement_pose_index = 0 - self._last_pose_time = rospy.Time.now() + self._last_pose_time = self.get_clock().now() self._bpm = 120 self._peak_delay_pose_count = 0 - self._rate = rospy.Rate(100) + self._time = self.create_timer(1 / 100, self._timer_callback) - self._hbba_filter_state = hbba_lite.OnOffHbbaFilterState('pose/filter_state') + self._hbba_filter_state = hbba_lite.OnOffHbbaFilterState(self, 'pose/filter_state') self._hbba_filter_state.on_changed(self._hbba_filter_state_cb) - self._bpm_sub = rospy.Subscriber('bpm', Float32, self._bpm_cb, queue_size=1) - self._beat_sub = rospy.Subscriber('beat', Bool, self._beat_cb, queue_size=1) + self._bpm_sub = self.create_subscription(Float32, 'bpm', self._bpm_cb, 1) + self._beat_sub = self.create_subscription(Bool, 'beat', self._beat_cb, 1) def _hbba_filter_state_cb(self, previous_is_filtering_all_messages, new_is_filtering_all_messages): pass def _bpm_cb(self, msg): if msg.data > 0: - with self._lock: - self._bpm = msg.data + self._bpm = msg.data def _beat_cb(self, msg): if msg.data: - with self._lock: - self._peak_delay_pose_count = self._find_peak_delay_pose_count() + self._peak_delay_pose_count = self._find_peak_delay_pose_count() def _find_peak_delay_pose_count(self): relative_index = float(self._current_movement_pose_index) / (len(self._current_movement['poses']) - 1) @@ -56,24 +57,23 @@ def _find_peak_delay_pose_count(self): return (closest_value - relative_index) * (len(self._current_movement['poses']) - 1) - def run(self): - while not rospy.is_shutdown(): - with self._lock: - if not self._hbba_filter_state.is_filtering_all_messages: - pose_duration = self._get_pose_duration() - if (rospy.Time.now() - self._last_pose_time) > pose_duration: - self._send_pose(self._current_movement['poses'][self._current_movement_pose_index]) - self._current_movement_pose_index += 1 - self._last_pose_time = rospy.Time.now() - - if self._current_movement_pose_index == len(self._current_movement['poses']): - self._current_movement_pose_index = 0 - self._update_movement() - else: + def _timer_callback(self): + if not self._hbba_filter_state.is_filtering_all_messages: + pose_duration = self._get_pose_duration() + if (self.get_clock().now() - self._last_pose_time) > pose_duration: + self._send_pose(self._current_movement['poses'][self._current_movement_pose_index]) + self._current_movement_pose_index += 1 + self._last_pose_time = self.get_clock().now() + + if self._current_movement_pose_index == len(self._current_movement['poses']): self._current_movement_pose_index = 0 - self._last_pose_time = rospy.Time.now() + self._update_movement() + else: + self._current_movement_pose_index = 0 + self._last_pose_time = self.get_clock().now() - self._rate.sleep() + def run(self): + rclpy.spin(self) def _update_movement(self): if random.random() < P_CHANGE_MOVEMENT: @@ -85,22 +85,9 @@ def _get_pose_duration(self): beat_duration = self._current_movement['beat_duration'] pose_count = len(self._current_movement['poses']) + self._peak_delay_pose_count - return rospy.Duration.from_sec(float(beat_duration) / pose_count / self._bpm * 60.0) + return Duration(seconds=float(beat_duration) / pose_count / self._bpm * 60.0) @abstractmethod def _send_pose(self, pose): """ Called with self._lock locked """ pass - - -def main(): - rospy.init_node('dance_node') - dance_node = DanceNode() - dance_node.run() - - -if __name__ == '__main__': - try: - main() - except rospy.ROSInterruptException: - pass diff --git a/ros/behaviors/dance/launch/test_dance.launch.xml b/ros/behaviors/dance/launch/test_dance.launch.xml new file mode 100644 index 00000000..0891b933 --- /dev/null +++ b/ros/behaviors/dance/launch/test_dance.launch.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ros/behaviors/dance/head_movements.json b/ros/behaviors/dance/movements/head_movements.json similarity index 100% rename from ros/behaviors/dance/head_movements.json rename to ros/behaviors/dance/movements/head_movements.json diff --git a/ros/behaviors/dance/led_colors.json b/ros/behaviors/dance/movements/led_colors.json similarity index 100% rename from ros/behaviors/dance/led_colors.json rename to ros/behaviors/dance/movements/led_colors.json diff --git a/ros/behaviors/dance/torso_movements.json b/ros/behaviors/dance/movements/torso_movements.json similarity index 100% rename from ros/behaviors/dance/torso_movements.json rename to ros/behaviors/dance/movements/torso_movements.json diff --git a/ros/behaviors/dance/package.xml b/ros/behaviors/dance/package.xml index f7134ee3..7c9e0b4f 100644 --- a/ros/behaviors/dance/package.xml +++ b/ros/behaviors/dance/package.xml @@ -1,77 +1,28 @@ - + + dance 0.0.0 The dance package + Marc-Antoine Maheux + GPL-3.0 license - - - - mahm1904 + ament_cmake + rclpy + daemon_ros_client + std_msgs + hbba_lite + t_top - - - - TODO + rosidl_default_runtime + ros2launch + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - rospy - roscpp - std_msgs - hbba_lite - t_top - daemon_ros_client - rospy - roscpp - std_msgs - hbba_lite - t_top - daemon_ros_client - rospy - roscpp - std_msgs - hbba_lite - t_top - daemon_ros_client - - - - - + ament_cmake diff --git a/ros/behaviors/dance/scripts/head_dance_node.py b/ros/behaviors/dance/scripts/head_dance_node.py index a6aa7fd0..3e3ff38b 100755 --- a/ros/behaviors/dance/scripts/head_dance_node.py +++ b/ros/behaviors/dance/scripts/head_dance_node.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 -import rospy +import rclpy + from geometry_msgs.msg import PoseStamped from t_top import HEAD_ZERO_Z @@ -8,8 +9,8 @@ class HeadDanceNode(PoseDanceNode): def __init__(self): - self._head_pose_pub = rospy.Publisher('dance/set_head_pose', PoseStamped, queue_size=5) - super(HeadDanceNode, self).__init__() + super().__init__('head_dance_node') + self._head_pose_pub = self.create_publisher(PoseStamped, 'dance/set_head_pose', 5) def _send_pose(self, pose): """ Called with self._lock locked """ @@ -17,28 +18,33 @@ def _send_pose(self, pose): pose_msg = PoseStamped() pose_msg.header.frame_id = 'stewart_base' - pose_msg.pose.position.x = pose[0] - pose_msg.pose.position.y = pose[1] - pose_msg.pose.position.z = HEAD_ZERO_Z + pose[2] + pose_msg.pose.position.x = float(pose[0]) + pose_msg.pose.position.y = float(pose[1]) + pose_msg.pose.position.z = float(HEAD_ZERO_Z + pose[2]) - pose_msg.pose.orientation.x = pose[3] - pose_msg.pose.orientation.y = pose[4] - pose_msg.pose.orientation.z = pose[5] - pose_msg.pose.orientation.w = pose[6] + pose_msg.pose.orientation.x = float(pose[3]) + pose_msg.pose.orientation.y = float(pose[4]) + pose_msg.pose.orientation.z = float(pose[5]) + pose_msg.pose.orientation.w = float(pose[6]) self._head_pose_pub.publish(pose_msg) else: - rospy.logerr('Invalid pose') + self.get_logger().error('Invalid pose') def main(): - rospy.init_node('head_dance_node') + rclpy.init() head_dance_node = HeadDanceNode() - head_dance_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + head_dance_node.run() + except KeyboardInterrupt: pass + finally: + head_dance_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/behaviors/dance/scripts/led_dance_node.py b/ros/behaviors/dance/scripts/led_dance_node.py old mode 100644 new mode 100755 index 010d59ca..ef5a1879 --- a/ros/behaviors/dance/scripts/led_dance_node.py +++ b/ros/behaviors/dance/scripts/led_dance_node.py @@ -1,7 +1,10 @@ +#!/usr/bin/env python3 + import json import random -import rospy +import rclpy +import rclpy.node from std_msgs.msg import Bool from daemon_ros_client.msg import LedColors @@ -9,16 +12,19 @@ import hbba_lite -class LedDanceNode: +class LedDanceNode(rclpy.node.Node): def __init__(self): - with open(rospy.get_param('~led_colors_file'), 'r') as f: + super().__init__('led_dance_node') + + led_colors_file = self.declare_parameter('led_colors_file', '').get_parameter_value().string_value + with open(led_colors_file, 'r') as f: self._none_led_colors, self._dance_led_colors = self._load_led_colors(json.load(f)) - self._led_colors_pub = hbba_lite.OnOffHbbaPublisher('dance/set_led_colors', LedColors, queue_size=1, + self._led_colors_pub = hbba_lite.OnOffHbbaPublisher(self, LedColors, 'dance/set_led_colors', 1, state_service_name='set_led_colors/filter_state') self._led_colors_pub.on_filter_state_changing(self._hbba_filter_state_cb) - self._beat_sub = rospy.Subscriber('beat', Bool, self._beat_cb, queue_size=1) + self._beat_sub = self.create_subscription(Bool, 'beat', self._beat_cb, 1) def _load_led_colors(self, json_dict): none_led_colors = LedColors() @@ -49,17 +55,22 @@ def _beat_cb(self, msg): self._led_colors_pub.publish(random.choice(self._dance_led_colors)) def run(self): - rospy.spin() + rclpy.spin(self) def main(): - rospy.init_node('led_dance_node') + rclpy.init() led_dance_node = LedDanceNode() - led_dance_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + led_dance_node.run() + except KeyboardInterrupt: pass + finally: + led_dance_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/behaviors/dance/scripts/torso_dance_node.py b/ros/behaviors/dance/scripts/torso_dance_node.py index 7189f92d..a1177ac4 100755 --- a/ros/behaviors/dance/scripts/torso_dance_node.py +++ b/ros/behaviors/dance/scripts/torso_dance_node.py @@ -1,57 +1,54 @@ #!/usr/bin/env python3 -import threading +import rclpy -import rospy from std_msgs.msg import Float32 from daemon_ros_client.msg import MotorStatus from dance.lib_pose_dance_node import PoseDanceNode -P_CHANGE_MOVEMENT = 0.25 - - class TorsoDanceNode(PoseDanceNode): def __init__(self): - self._current_torso_orientation_lock = threading.Lock() + super().__init__('torso_dance_node') + self._current_torso_orientation = 0.0 self._torso_offset = 0.0 - self._torso_orientation_pub = rospy.Publisher('dance/set_torso_orientation', Float32, queue_size=5) + self._torso_orientation_pub = self.create_publisher(Float32, 'dance/set_torso_orientation', 5) - super(TorsoDanceNode, self).__init__() - - self._motor_status_sub = rospy.Subscriber('daemon/motor_status', MotorStatus, self._motor_status_cb, queue_size=1) + self._motor_status_sub = self.create_subscription(MotorStatus, 'daemon/motor_status', self._motor_status_cb, 1) def _hbba_filter_state_cb(self, previous_is_filtering_all_messages, new_is_filtering_all_messages): if previous_is_filtering_all_messages and not new_is_filtering_all_messages: - with self._lock, self._current_torso_orientation_lock: - self._torso_offset = self._current_torso_orientation + self._torso_offset = self._current_torso_orientation def _motor_status_cb(self, msg): - with self._current_torso_orientation_lock: - self._current_torso_orientation = msg.torso_orientation + self._current_torso_orientation = msg.torso_orientation def _send_pose(self, pose): - """ Called with self._lock locked """ if len(pose) == 1: pose_msg = Float32() - pose_msg.data = pose[0] + self._torso_offset + pose_msg.data = float(pose[0] + self._torso_offset) self._torso_orientation_pub.publish(pose_msg) else: - rospy.logerr('Invalid pose') + self.get_logger().error('Invalid pose') def main(): - rospy.init_node('torso_dance_node') + rclpy.init() torso_dance_node = TorsoDanceNode() - torso_dance_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + torso_dance_node.run() + except KeyboardInterrupt: pass + finally: + torso_dance_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/behaviors/dance/setup.py b/ros/behaviors/dance/setup.py deleted file mode 100644 index 250d9983..00000000 --- a/ros/behaviors/dance/setup.py +++ /dev/null @@ -1,12 +0,0 @@ -## ! DO NOT MANUALLY INVOKE THIS setup.py, USE CATKIN INSTEAD - -from setuptools import setup -from catkin_pkg.python_setup import generate_distutils_setup - -# fetch values from package.xml -setup_args = generate_distutils_setup( - packages=['dance'], - package_dir={'': 'src'}, -) - -setup(**setup_args) diff --git a/ros/behaviors/explore/CMakeLists.txt b/ros/behaviors/explore/CMakeLists.txt index 32770381..35e8da62 100644 --- a/ros/behaviors/explore/CMakeLists.txt +++ b/ros/behaviors/explore/CMakeLists.txt @@ -1,207 +1,32 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(explore) -## Compile as C++11, supported in ROS Kinetic and newer -# add_compile_options(-std=c++11) - -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - hbba_lite - rospy - t_top - std_msgs - ) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -# add_message_files( -# FILES -# Message1.msg -# Message2.msg -# ) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -# generate_messages( -# DEPENDENCIES -# std_msgs # Or other packages containing msgs -# ) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( - # INCLUDE_DIRS include - # LIBRARIES explore - # CATKIN_DEPENDS hbba_lite rospy t_top - # DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( - # include - ${catkin_INCLUDE_DIRS} +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclpy REQUIRED) +find_package(daemon_ros_client REQUIRED) +find_package(std_msgs REQUIRED) +find_package(hbba_lite REQUIRED) +find_package(t_top REQUIRED) + +# Python Nodes +install(PROGRAMS + scripts/explore_node.py + DESTINATION lib/${PROJECT_NAME} ) -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/explore.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -# add_executable(${PROJECT_NAME}_node src/explore_node.cpp) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -# target_link_libraries(${PROJECT_NAME}_node -# ${catkin_LIBRARIES} -# ) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -# catkin_install_python(PROGRAMS -# scripts/my_python_script -# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_explore.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() - -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/behaviors/explore/README.md b/ros/behaviors/explore/README.md index b4787c5a..18658c3c 100644 --- a/ros/behaviors/explore/README.md +++ b/ros/behaviors/explore/README.md @@ -10,10 +10,10 @@ This node makes T-Top explore its surrounding. #### Parameters -- `simulation` (bool): Indicates if it's used in the simulation. -- `explore_frequency` (double): The frequency at which T-Top explores its surrounding. -- `torso_speed_rad_sec` (double): The torso speed in rad/s. -- `head_speed_rad_sec` (double): The head speed in rad/s. +- `simulation` (bool): Indicates if it's used in the simulation. The default value is false. +- `explore_frequency` (double): The frequency at which T-Top explores its surrounding. The default value is 0.00833333333. +- `torso_speed_rad_sec` (double): The torso speed in rad/s. The default value is 0.5. +- `head_speed_rad_sec` (double): The head speed in rad/s. The default value is 0.5. #### Subscribed Topics @@ -21,14 +21,14 @@ This node makes T-Top explore its surrounding. #### Published Topics -- `explore/set_head_pose` ([geometry_msgs/PoseStamped](http://docs.ros.org/en/noetic/api/geometry_msgs/html/msg/PoseStamped.html)): +- `explore/set_head_pose` ([geometry_msgs/PoseStamped](https://docs.ros.org/en/humble/p/geometry_msgs/interfaces/msg/PoseStamped.html)): The head pose. -- `explore/set_torso_orientation` ([std_msgs/Float32](http://docs.ros.org/en/noetic/api/std_msgs/html/msg/Float32.html)): The +- `explore/set_torso_orientation` ([std_msgs/Float32](https://docs.ros.org/en/humble/p/std_msgs/interfaces/msg/Float32.html)): The torso orientation. -- `explore/done` ([std_msgs/Empty](http://docs.ros.org/en/noetic/api/std_msgs/html/msg/Empty.html)): Indicates that the +- `explore/done` ([std_msgs/Empty](https://docs.ros.org/en/humble/p/std_msgs/interfaces/msg/Empty.html)): Indicates that the explore moves are finished. #### Services -- `pose/filter_state` ([hbba_lite/SetOnOffFilterState](../../hbba_lite/srv/SetOnOffFilterState.srv)): The HBBA filter +- `pose/filter_state` ([hbba_lite_srvs/SetOnOffFilterState](../../utils/hbba_lite/hbba_lite_srvs/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the behavior. diff --git a/ros/behaviors/explore/package.xml b/ros/behaviors/explore/package.xml index d9cff3f7..885224ee 100644 --- a/ros/behaviors/explore/package.xml +++ b/ros/behaviors/explore/package.xml @@ -1,71 +1,27 @@ - + + explore 0.0.0 The explore package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rclpy + daemon_ros_client + std_msgs + hbba_lite + t_top - - - - TODO + rosidl_default_runtime + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - hbba_lite - rospy - t_top - std_msgs - hbba_lite - rospy - t_top - std_msgs - hbba_lite - rospy - t_top - std_msgs - - - - - + ament_cmake diff --git a/ros/behaviors/explore/scripts/explore_node.py b/ros/behaviors/explore/scripts/explore_node.py index 44af2f98..5667a89d 100755 --- a/ros/behaviors/explore/scripts/explore_node.py +++ b/ros/behaviors/explore/scripts/explore_node.py @@ -1,6 +1,9 @@ #!/usr/bin/env python3 -import rospy +import rclpy +import rclpy.node +import rclpy.executors + from std_msgs.msg import Empty from t_top import MovementCommands, HEAD_ZERO_Z @@ -9,49 +12,59 @@ INACTIVE_SLEEP_DURATION = 0.1 -class ExploreNode: +class ExploreNode(rclpy.node.Node): def __init__(self): - self._simulation = rospy.get_param('~simulation') - self._rate = rospy.Rate(rospy.get_param('~explore_frequency')) - self._torso_speed = rospy.get_param('~torso_speed_rad_sec') - self._head_speed = rospy.get_param('~head_speed_rad_sec') + super().__init__('explore_node') + + self._simulation = self.declare_parameter('simulation', False).get_parameter_value().bool_value + self._explore_frequency = self.declare_parameter('explore_frequency', 0.00833333333).get_parameter_value().double_value + self._torso_speed = self.declare_parameter('torso_speed_rad_sec', 0.5).get_parameter_value().double_value + self._head_speed = self.declare_parameter('head_speed_rad_sec', 0.5).get_parameter_value().double_value + + self._timer = self.create_timer(1 / self._explore_frequency, self._timer_callback) + + self._movement_commands = MovementCommands(self, self._simulation, namespace='explore') + self._done_pub = self.create_publisher(Empty, 'explore/done', 5) + + def _timer_callback(self): + if self._movement_commands.is_filtering_all_messages: + return + + self._movement_commands.move_torso(0, should_wait=True, speed_rad_sec=self._torso_speed) + self._movement_commands.move_head([0, 0, HEAD_ZERO_Z, 0, -0.3, 0], should_wait=True, speed_rad_sec=self._head_speed) + self._movement_commands.move_torso(1.57, should_wait=False, speed_rad_sec=self._torso_speed) + self._movement_commands.move_torso(3.14, should_wait=True, speed_rad_sec=self._torso_speed) + self._movement_commands.move_head([0, 0, HEAD_ZERO_Z, 0, 0.15, 0], should_wait=True, speed_rad_sec=self._head_speed) + self._movement_commands.move_torso(1.57, should_wait=False, speed_rad_sec=self._torso_speed) + self._movement_commands.move_torso(0, should_wait=False, speed_rad_sec=self._torso_speed) + self._movement_commands.move_torso(-1.57, should_wait=False, speed_rad_sec=self._torso_speed) + self._movement_commands.move_torso(-3.14, should_wait=True, speed_rad_sec=self._torso_speed) + self._movement_commands.move_head([0, 0, HEAD_ZERO_Z, 0, -0.3, 0], should_wait=True, speed_rad_sec=self._head_speed) + self._movement_commands.move_torso(-1.57, should_wait=False, speed_rad_sec=self._torso_speed) + self._movement_commands.move_torso(0, should_wait=True, speed_rad_sec=self._torso_speed) + self._movement_commands.move_head([0, 0, HEAD_ZERO_Z, 0, 0, 0], should_wait=True, speed_rad_sec=self._head_speed) - self._movement_commands = MovementCommands(self._simulation, namespace='explore') - self._done_pub = rospy.Publisher('explore/done', Empty, queue_size=5) + self._done_pub.publish(Empty()) def run(self): - while not rospy.is_shutdown(): - if self._movement_commands.is_filtering_all_messages: - rospy.sleep(INACTIVE_SLEEP_DURATION) - continue - - self._movement_commands.move_torso(0, should_wait=True, speed_rad_sec=self._torso_speed) - self._movement_commands.move_head([0, 0, HEAD_ZERO_Z, 0, -0.3, 0], should_wait=True, speed_rad_sec=self._head_speed) - self._movement_commands.move_torso(1.57, should_wait=False, speed_rad_sec=self._torso_speed) - self._movement_commands.move_torso(3.14, should_wait=True, speed_rad_sec=self._torso_speed) - self._movement_commands.move_head([0, 0, HEAD_ZERO_Z, 0, 0.15, 0], should_wait=True, speed_rad_sec=self._head_speed) - self._movement_commands.move_torso(1.57, should_wait=False, speed_rad_sec=self._torso_speed) - self._movement_commands.move_torso(0, should_wait=False, speed_rad_sec=self._torso_speed) - self._movement_commands.move_torso(-1.57, should_wait=False, speed_rad_sec=self._torso_speed) - self._movement_commands.move_torso(-3.14, should_wait=True, speed_rad_sec=self._torso_speed) - self._movement_commands.move_head([0, 0, HEAD_ZERO_Z, 0, -0.3, 0], should_wait=True, speed_rad_sec=self._head_speed) - self._movement_commands.move_torso(-1.57, should_wait=False, speed_rad_sec=self._torso_speed) - self._movement_commands.move_torso(0, should_wait=True, speed_rad_sec=self._torso_speed) - self._movement_commands.move_head([0, 0, HEAD_ZERO_Z, 0, 0, 0], should_wait=True, speed_rad_sec=self._head_speed) - - self._done_pub.publish(Empty()) - - self._rate.sleep() + executor = rclpy.executors.MultiThreadedExecutor(num_threads=2) + executor.add_node(self) + executor.spin() def main(): - rospy.init_node('explore_node') + rclpy.init() explore_node = ExploreNode() - explore_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + explore_node.run() + except KeyboardInterrupt: pass + finally: + explore_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/behaviors/face_following/CMakeLists.txt b/ros/behaviors/face_following/CMakeLists.txt index b8336576..e5e87952 100644 --- a/ros/behaviors/face_following/CMakeLists.txt +++ b/ros/behaviors/face_following/CMakeLists.txt @@ -1,212 +1,40 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(face_following) -## Compile as C++11, supported in ROS Kinetic and newer -# add_compile_options(-std=c++11) -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - std_msgs - geometry_msgs - hbba_lite - rospy - t_top - tf - video_analyzer - person_identification +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclpy REQUIRED) +find_package(std_msgs REQUIRED) +find_package(geometry_msgs REQUIRED) +find_package(hbba_lite REQUIRED) +find_package(t_top REQUIRED) +find_package(tf2 REQUIRED) +find_package(tf2_ros REQUIRED) +find_package(perception_msgs REQUIRED) + +# Python Librairies +ament_python_install_package(${PROJECT_NAME}) + +# Python Nodes +install(PROGRAMS + scripts/nearest_face_following_node.py + scripts/specific_face_following_node.py + DESTINATION lib/${PROJECT_NAME} ) -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -# add_message_files( -# FILES -# Message1.msg -# Message2.msg -# ) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -# generate_messages( -# DEPENDENCIES -# geometry_msgs# std_msgs -# ) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( - # INCLUDE_DIRS include - # LIBRARIES face_following - # CATKIN_DEPENDS geometry_msgs hbba_lite rospy std_msgs t_top tf - # DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( - # include - ${catkin_INCLUDE_DIRS} -) - -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/face_following.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -# add_executable(${PROJECT_NAME}_node src/face_following_node.cpp) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -# target_link_libraries(${PROJECT_NAME}_node -# ${catkin_LIBRARIES} -# ) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -catkin_install_python(PROGRAMS - scripts/nearest_face_following_node.py - scripts/specific_face_following_node.py - DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -) - -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_face_following.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() - -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/behaviors/face_following/README.md b/ros/behaviors/face_following/README.md index b97c10ff..4c1b08b7 100644 --- a/ros/behaviors/face_following/README.md +++ b/ros/behaviors/face_following/README.md @@ -10,31 +10,31 @@ This node makes T-Top follow the nearest face. #### Parameters -- `simulation` (bool): Indicates if it's used in the simulation. -- `control_frequency` (double): The frequency at which the pose messages are sent. -- `torso_control_alpha` (double): The low-pass filter parameter for the torso pose. -- `head_control_p_gain` (double): The controller proportional gain for the head pose. -- `head_enabled` (bool): Indicates if the head will move. -- `min_head_pitch_rad` (double): The minimum pitch angle in radian of the head. -- `max_head_pitch_rad` (double): The maximum pitch angle in radian of the head. -- `nose_confidence_threshold` (double): The confidence threshold for the nose keypoint. +- `simulation` (bool): Indicates if it's used in the simulation. The default value is false. +- `control_frequency` (double): The frequency at which the pose messages are sent. The default value is 30. +- `torso_control_alpha` (double): The low-pass filter parameter for the torso pose. The default value is 0.2. +- `head_control_p_gain` (double): The controller proportional gain for the head pose. The default value is 0.175. +- `head_enabled` (bool): Indicates if the head will move. The default value is true. +- `min_head_pitch_rad` (double): The minimum pitch angle in radian of the head. The default value is -0.35. +- `max_head_pitch_rad` (double): The maximum pitch angle in radian of the head. The default value is 0.35. +- `nose_confidence_threshold` (double): The confidence threshold for the nose keypoint. The default value is 0.4. #### Subscribed Topics - `daemon/motor_status` ([daemon_ros_client/MotorStatus](../../daemon_ros_client/msg/MotorStatus.msg)): The motor status. -- `video_analysis` ([video_analyzer/VideoAnalysis](../../perceptions/video_analyzer/msg/VideoAnalysis.msg)): The video +- `video_analysis` ([perception_msgs/VideoAnalysis](../../perceptions/perception_msgs/msg/VideoAnalysis.msg)): The video analysis containing the detected objects. The video analysis must contain 3d positions. #### Published Topics -- `nearest_face_following/set_head_pose` ([geometry_msgs/PoseStamped](http://docs.ros.org/en/noetic/api/geometry_msgs/html/msg/PoseStamped.html)): +- `nearest_face_following/set_head_pose` ([geometry_msgs/PoseStamped](https://docs.ros.org/en/humble/p/geometry_msgs/interfaces/msg/PoseStamped.html)): The head pose. -- `nearest_face_following/set_torso_orientation` ([std_msgs/Float32](http://docs.ros.org/en/noetic/api/std_msgs/html/msg/Float32.html)): +- `nearest_face_following/set_torso_orientation` ([std_msgs/Float32](https://docs.ros.org/en/humble/p/std_msgs/interfaces/msg/Float32.html)): The torso orientation. #### Services -- `pose/filter_state` ([hbba_lite/SetOnOffFilterState](../../hbba_lite/srv/SetOnOffFilterState.srv)): The HBBA filter +- `pose/filter_state` ([hbba_lite_srvs/SetOnOffFilterState](../../utils/hbba_lite/hbba_lite_srvs/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the behavior. @@ -44,29 +44,29 @@ This node makes T-Top follow the face of the specified person. #### Parameters -- `simulation` (bool): Indicates if it's used in the simulation. -- `control_frequency` (double): The frequency at which the pose messages are sent. -- `torso_control_alpha` (double): The low-pass filter parameter for the torso pose. -- `head_control_p_gain` (double): The controller proportional gain for the head pose. -- `head_enabled` (bool): Indicates if the head will move. -- `min_head_pitch_rad` (double): The minimum pitch angle in radian of the head. -- `max_head_pitch_rad` (double): The maximum pitch angle in radian of the head. -- `direction_frame_id` (string): The audio analysis frame id. +- `simulation` (bool): Indicates if it's used in the simulation. The default value is false. +- `control_frequency` (double): The frequency at which the pose messages are sent. The default value is 30. +- `torso_control_alpha` (double): The low-pass filter parameter for the torso pose. The default value is 0.2. +- `head_control_p_gain` (double): The controller proportional gain for the head pose. The default value is 0.175. +- `head_enabled` (bool): Indicates if the head will move. The default value is true. +- `min_head_pitch_rad` (double): The minimum pitch angle in radian of the head. The default value is -0.35. +- `max_head_pitch_rad` (double): The maximum pitch angle in radian of the head. The default value is 0.35. +- `direction_frame_id` (string): The audio analysis frame id. The default value is odas. #### Subscribed Topics -- `person_names` ([person_identification/PersonNames](../../perceptions/person_identification/msg/PersonNames.msg)): +- `person_names` ([person_identification/PersonNames](../../perceptions/perception_msgs/msg/PersonNames.msg)): The person names. - `daemon/motor_status` ([daemon_ros_client/MotorStatus](../../daemon_ros_client/msg/MotorStatus.msg)): The motor status. #### Published Topics -- `specific_face_following/set_head_pose` ([geometry_msgs/PoseStamped](http://docs.ros.org/en/noetic/api/geometry_msgs/html/msg/PoseStamped.html)): +- `specific_face_following/set_head_pose` ([geometry_msgs/PoseStamped](https://docs.ros.org/en/humble/p/geometry_msgs/interfaces/msg/PoseStamped.html)): The head pose. -- `specific_face_following/set_torso_orientation` ([std_msgs/Float32](http://docs.ros.org/en/noetic/api/std_msgs/html/msg/Float32.html)): +- `specific_face_following/set_torso_orientation` ([std_msgs/Float32](https://docs.ros.org/en/humble/p/std_msgs/interfaces/msg/Float32.html)): The torso orientation. #### Services -- `pose/filter_state` ([hbba_lite/SetOnOffFilterState](../../hbba_lite/srv/SetOnOffFilterState.srv)): The HBBA filter +- `pose/filter_state` ([hbba_lite_srvs/SetOnOffFilterState](../../utils/hbba_lite/hbba_lite_srvs/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the behavior. diff --git a/ros/behaviors/led_animations/src/led_animations/__init__.py b/ros/behaviors/face_following/face_following/__init__.py similarity index 100% rename from ros/behaviors/led_animations/src/led_animations/__init__.py rename to ros/behaviors/face_following/face_following/__init__.py diff --git a/ros/behaviors/face_following/face_following/lib_face_following_node.py b/ros/behaviors/face_following/face_following/lib_face_following_node.py new file mode 100644 index 00000000..1a643bab --- /dev/null +++ b/ros/behaviors/face_following/face_following/lib_face_following_node.py @@ -0,0 +1,71 @@ +import math + +import rclpy +import rclpy.node +import rclpy.executors + +from t_top import MovementCommands, HEAD_ZERO_Z, HEAD_POSE_PITCH_INDEX + + +TARGET_HEAD_IMAGE_Y = 0.5 + + +class FaceFollowingNode(rclpy.node.Node): + def __init__(self, node_name, namespace): + super().__init__(node_name) + + self._simulation = self.declare_parameter('simulation', False).get_parameter_value().bool_value + self._control_frequency = self.declare_parameter('control_frequency', 30.0).get_parameter_value().double_value + self._torso_control_alpha = self.declare_parameter('torso_control_alpha', 0.2).get_parameter_value().double_value + self._head_control_p_gain = self.declare_parameter('head_control_p_gain', 0.175).get_parameter_value().double_value + self._head_enabled = self.declare_parameter('head_enabled', True).get_parameter_value().bool_value + self._min_head_pitch = self.declare_parameter('min_head_pitch_rad', -0.35).get_parameter_value().double_value + self._max_head_pitch = self.declare_parameter('max_head_pitch_rad', 0.35).get_parameter_value().double_value + + self._target_torso_yaw = None + self._current_head_image_y = None + + self._movement_commands = MovementCommands(self, self._simulation, namespace) + + self._timer = self.create_timer(1 / self._control_frequency, self._timer_callback) + + def _update(self, yaw, head_image_y): + if yaw is None or math.isfinite(yaw): + self._target_torso_yaw = yaw + if head_image_y is None or math.isfinite(head_image_y): + self._current_head_image_y = head_image_y + + def _timer_callback(self): + if self._movement_commands.is_filtering_all_messages: + return + + self._update_torso() + if self._head_enabled: + self._update_head() + + def run(self): + executor = rclpy.executors.MultiThreadedExecutor(num_threads=2) + executor.add_node(self) + executor.spin() + + def _update_torso(self): + if self._target_torso_yaw is None: + return + + distance = self._target_torso_yaw - self._movement_commands.current_torso_pose + if distance < -math.pi: + distance = 2 * math.pi + distance + elif distance > math.pi: + distance = -(2 * math.pi - distance) + + pose = self._movement_commands.current_torso_pose + self._torso_control_alpha * distance + self._movement_commands.move_torso(pose) + + def _update_head(self): + if self._current_head_image_y is None: + return + + current_pitch = self._movement_commands.current_head_pose[HEAD_POSE_PITCH_INDEX] + pitch = current_pitch + self._head_control_p_gain * (self._current_head_image_y - TARGET_HEAD_IMAGE_Y) + pitch = max(self._min_head_pitch, min(pitch, self._max_head_pitch)) + self._movement_commands.move_head([0, 0, HEAD_ZERO_Z, 0, pitch, 0]) diff --git a/ros/behaviors/face_following/package.xml b/ros/behaviors/face_following/package.xml index ca0a9fda..d10e7e65 100644 --- a/ros/behaviors/face_following/package.xml +++ b/ros/behaviors/face_following/package.xml @@ -1,83 +1,30 @@ - + + face_following 0.0.0 The face_following package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rclpy + std_msgs + geometry_msgs + hbba_lite + t_top + tf2 + tf2_ros + perception_msgs - - - - TODO + rosidl_default_runtime + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - std_msgs - geometry_msgs - hbba_lite - rospy - t_top - tf - video_analyzer - person_identification - std_msgs - geometry_msgs - hbba_lite - rospy - t_top - tf - video_analyzer - person_identification - std_msgs - geometry_msgs - hbba_lite - rospy - t_top - tf - video_analyzer - person_identification - - - - - + ament_cmake diff --git a/ros/behaviors/face_following/scripts/nearest_face_following_node.py b/ros/behaviors/face_following/scripts/nearest_face_following_node.py index a3f464dc..7561d086 100755 --- a/ros/behaviors/face_following/scripts/nearest_face_following_node.py +++ b/ros/behaviors/face_following/scripts/nearest_face_following_node.py @@ -1,11 +1,16 @@ #!/usr/bin/env python3 -import rospy -import tf +import rclpy + +from tf2_ros import TransformException +from tf2_ros.buffer import Buffer +from tf2_ros.transform_listener import TransformListener +import tf2_geometry_msgs + from geometry_msgs.msg import PointStamped -from video_analyzer.msg import VideoAnalysis +from perception_msgs.msg import VideoAnalysis -from t_top import vector_to_angles, HEAD_ZERO_Z +from t_top import vector_to_angles from face_following.lib_face_following_node import FaceFollowingNode @@ -15,21 +20,26 @@ class NearestFaceFollowingNode(FaceFollowingNode): def __init__(self): - super().__init__(namespace='nearest_face_following') - self._nose_confidence_threshold = rospy.get_param('~nose_confidence_threshold') + super().__init__(node_name='nearest_face_following_node', namespace='nearest_face_following') + self._nose_confidence_threshold = self.declare_parameter('nose_confidence_threshold', 0.4).get_parameter_value().double_value - self._tf_listener = tf.TransformListener() - self._video_analysis_sub = rospy.Subscriber('video_analysis', VideoAnalysis, self._video_analysis_cb, queue_size=1) + self._tf_buffer = Buffer() + self._tf_listener = TransformListener(self._tf_buffer, self) + + self._video_analysis_sub = self.create_subscription(VideoAnalysis, 'video_analysis', self._video_analysis_cb, 1) def _video_analysis_cb(self, msg): if self._movement_commands.is_filtering_all_messages: return if not msg.contains_3d_positions: - rospy.logerr('The video analysis must contain 3d positions.') + self.get_logger().error('The video analysis must contain 3d positions.') return - yaw, head_image_y = self._find_nearest_face_yaw_head_image_y(msg.objects, msg.header) - self._update(yaw, head_image_y) + try: + yaw, head_image_y = self._find_nearest_face_yaw_head_image_y(msg.objects, msg.header) + self._update(yaw, head_image_y) + except TransformException as ex: + self.get_logger().warn(f'Could not transform: {ex}') def _find_nearest_face_yaw_head_image_y(self, objects, header): nose_points_3d = [] @@ -57,22 +67,27 @@ def _transform_point(self, point, header): temp_in_point.point.y = point.y temp_in_point.point.z = point.z - base_link_point = self._tf_listener.transformPoint('/base_link', temp_in_point) - stewart_base_point = self._tf_listener.transformPoint('/stewart_base', temp_in_point) + transform = self._tf_buffer.lookup_transform('base_link', header.frame_id, rclpy.time.Time.from_msg(header.stamp)) + base_link_point = tf2_geometry_msgs.do_transform_point(temp_in_point, transform) point.x = base_link_point.point.x point.y = base_link_point.point.y - point.z = stewart_base_point.point.z - HEAD_ZERO_Z + point.z = base_link_point.point.z def main(): - rospy.init_node('nearest_face_following_node') - face_following_node = NearestFaceFollowingNode() - face_following_node.run() - + rclpy.init() + nearest_face_following_node = NearestFaceFollowingNode() -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + nearest_face_following_node.run() + except KeyboardInterrupt: pass + finally: + nearest_face_following_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/behaviors/face_following/scripts/specific_face_following_node.py b/ros/behaviors/face_following/scripts/specific_face_following_node.py index 11a324ff..0a64b9d2 100755 --- a/ros/behaviors/face_following/scripts/specific_face_following_node.py +++ b/ros/behaviors/face_following/scripts/specific_face_following_node.py @@ -1,10 +1,9 @@ #!/usr/bin/env python3 -import threading +import rclpy -import rospy from std_msgs.msg import String -from person_identification.msg import PersonNames +from perception_msgs.msg import PersonNames from t_top import vector_to_angles @@ -13,33 +12,28 @@ class SpecificFaceFollowingNode(FaceFollowingNode): def __init__(self): - super().__init__(namespace='specific_face_following') - self._direction_frame_id = rospy.get_param('~direction_frame_id') + super().__init__(node_name='specific_face_following_node', namespace='specific_face_following') + self._direction_frame_id = self.declare_parameter('direction_frame_id', 'odas').get_parameter_value().string_value - self._target_name_lock = threading.Lock() self._target_name = None - self._target_name_sub = rospy.Subscriber('target_name', String, self._target_name_cb, queue_size=1) - self._person_names_sub = rospy.Subscriber('person_names', PersonNames, self._person_names_cb, queue_size=1) + self._target_name_sub = self.create_subscription(String, 'target_name', self._target_name_cb, 1) + self._person_names_sub = self.create_subscription(PersonNames, 'person_names', self._person_names_cb, 1) def _target_name_cb(self, msg): - with self._target_name_lock: - self._target_name = msg.data + self._target_name = msg.data def _person_names_cb(self, msg): if self._movement_commands.is_filtering_all_messages: return - with self._target_name_lock: - target_name = self._target_name - for person_name in msg.names: - if person_name.detection_type != 'voice' and person_name.name == target_name: + if person_name.detection_type != 'voice' and person_name.name == self._target_name: if person_name.frame_id != self._direction_frame_id: - rospy.logerr(f'Invalid direction frame id ({person_name.frame_id} != {self._direction_frame_id})') + self.get_logger().error(f'Invalid direction frame id ({person_name.frame_id} != {self._direction_frame_id})') return if len(person_name.direction) == 0 or len(person_name.position_2d) == 0: - rospy.logerr(f'The direction and position_2d must not be empty.') + self.get_logger().error(f'The direction and position_2d must not be empty.') return yaw, _ = vector_to_angles(person_name.direction[0]) @@ -49,13 +43,18 @@ def _person_names_cb(self, msg): def main(): - rospy.init_node('specific_face_following_node') - face_following_node = SpecificFaceFollowingNode() - face_following_node.run() - + rclpy.init() + specific_face_following_node = SpecificFaceFollowingNode() -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + specific_face_following_node.run() + except KeyboardInterrupt: pass + finally: + specific_face_following_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/behaviors/face_following/setup.py b/ros/behaviors/face_following/setup.py deleted file mode 100644 index d3b27af4..00000000 --- a/ros/behaviors/face_following/setup.py +++ /dev/null @@ -1,12 +0,0 @@ -## ! DO NOT MANUALLY INVOKE THIS setup.py, USE CATKIN INSTEAD - -from setuptools import setup -from catkin_pkg.python_setup import generate_distutils_setup - -# fetch values from package.xml -setup_args = generate_distutils_setup( - packages=['face_following'], - package_dir={'': 'src'}, -) - -setup(**setup_args) diff --git a/ros/behaviors/face_following/src/face_following/lib_face_following_node.py b/ros/behaviors/face_following/src/face_following/lib_face_following_node.py deleted file mode 100644 index 8e971edc..00000000 --- a/ros/behaviors/face_following/src/face_following/lib_face_following_node.py +++ /dev/null @@ -1,69 +0,0 @@ -import math -import threading - -import rospy - -from t_top import MovementCommands, HEAD_ZERO_Z, HEAD_POSE_PITCH_INDEX - - -TARGET_HEAD_IMAGE_Y = 0.5 - - -class FaceFollowingNode: - def __init__(self, namespace): - self._simulation = rospy.get_param('~simulation') - self._rate = rospy.Rate(rospy.get_param('~control_frequency')) - self._torso_control_alpha = rospy.get_param('~torso_control_alpha') - self._head_control_p_gain = rospy.get_param('~head_control_p_gain') - self._head_enabled = rospy.get_param('~head_enabled') - self._min_head_pitch = rospy.get_param('~min_head_pitch_rad') - self._max_head_pitch = rospy.get_param('~max_head_pitch_rad') - - self._target_lock = threading.Lock() - self._target_torso_yaw = None - self._current_head_image_y = None - - self._movement_commands = MovementCommands(self._simulation, namespace) - - def _update(self, yaw, head_image_y): - with self._target_lock: - if yaw is None or math.isfinite(yaw): - self._target_torso_yaw = yaw - if head_image_y is None or math.isfinite(head_image_y): - self._current_head_image_y = head_image_y - - def run(self): - while not rospy.is_shutdown(): - self._rate.sleep() - if self._movement_commands.is_filtering_all_messages: - continue - - self._update_torso() - if self._head_enabled: - self._update_head() - - def _update_torso(self): - with self._target_lock: - target_torso_yaw = self._target_torso_yaw - if target_torso_yaw is None: - return - - distance = target_torso_yaw - self._movement_commands.current_torso_pose - if distance < -math.pi: - distance = 2 * math.pi + distance - elif distance > math.pi: - distance = -(2 * math.pi - distance) - - pose = self._movement_commands.current_torso_pose + self._torso_control_alpha * distance - self._movement_commands.move_torso(pose) - - def _update_head(self): - with self._target_lock: - current_head_image_y = self._current_head_image_y - if current_head_image_y is None: - return - - current_pitch = self._movement_commands.current_head_pose[HEAD_POSE_PITCH_INDEX] - pitch = current_pitch + self._head_control_p_gain * (current_head_image_y - TARGET_HEAD_IMAGE_Y) - pitch = max(self._min_head_pitch, min(pitch, self._max_head_pitch)) - self._movement_commands.move_head([0, 0, HEAD_ZERO_Z, 0, pitch, 0]) diff --git a/ros/behaviors/gesture/CMakeLists.txt b/ros/behaviors/gesture/CMakeLists.txt index 5efe4fca..c64c1411 100644 --- a/ros/behaviors/gesture/CMakeLists.txt +++ b/ros/behaviors/gesture/CMakeLists.txt @@ -1,205 +1,33 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(gesture) -## Compile as C++11, supported in ROS Kinetic and newer -# add_compile_options(-std=c++11) - -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - hbba_lite - rospy - std_msgs - message_generation - t_top - ) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -add_message_files( - FILES - GestureName.msg - Done.msg +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclpy REQUIRED) +find_package(daemon_ros_client REQUIRED) +find_package(std_msgs REQUIRED) +find_package(hbba_lite REQUIRED) +find_package(t_top REQUIRED) +find_package(behavior_msgs REQUIRED) + +# Python Nodes +install(PROGRAMS + scripts/gesture_node.py + DESTINATION lib/${PROJECT_NAME} ) -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -generate_messages() - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( - # INCLUDE_DIRS include - # LIBRARIES gesture - # CATKIN_DEPENDS hbba_lite rospy std_msgs t_top - # DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( - # include - ${catkin_INCLUDE_DIRS} -) - -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/gesture.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -# add_executable(${PROJECT_NAME}_node src/gesture_node.cpp) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -# target_link_libraries(${PROJECT_NAME}_node -# ${catkin_LIBRARIES} -# ) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -catkin_install_python(PROGRAMS - scripts/gesture_node.py - DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} - ) - -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_gesture.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() - -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/behaviors/gesture/README.md b/ros/behaviors/gesture/README.md index 831a1810..dc25624a 100644 --- a/ros/behaviors/gesture/README.md +++ b/ros/behaviors/gesture/README.md @@ -10,23 +10,23 @@ This node makes T-Top perform gestures. #### Parameters -- `simulation` (bool): Indicates if it's used in the simulation. +- `simulation` (bool): Indicates if it's used in the simulation. The default value is false. #### Subscribed Topics - `daemon/motor_status` ([daemon_ros_client/MotorStatus](../../daemon_ros_client/msg/MotorStatus.msg)): The motor status. -- `gesture/name` ([gesture/GestureName](msg/GestureName.msg)): The gesture to perform. +- `gesture/name` ([behavior_msgs/GestureName](../behavior_msgs/msg/GestureName.msg)): The gesture to perform. - Supported values : `yes`, `no`, `maybe`, `origin_all`, `origin_head`, `origin_torso` #### Published Topics -- `gesture/set_head_pose` ([geometry_msgs/PoseStamped](http://docs.ros.org/en/noetic/api/geometry_msgs/html/msg/PoseStamped.html)): +- `gesture/set_head_pose` ([geometry_msgs/PoseStamped](https://docs.ros.org/en/humble/p/geometry_msgs/interfaces/msg/PoseStamped.html)): The head pose. -- `gesture/set_torso_orientation` ([std_msgs/Float32](http://docs.ros.org/en/noetic/api/std_msgs/html/msg/Float32.html)): The +- `gesture/set_torso_orientation` ([std_msgs/Float32](https://docs.ros.org/en/humble/p/std_msgs/interfaces/msg/Float32.html)): The torso orientation. -- `gesture/done` ([gesture/Done](msg/Done.msg)): Indicates that the gesture is finished. +- `gesture/done` ([behavior_msgs/Done](../behavior_msgs/msg/Done.msg)): Indicates that the gesture is finished. #### Services -- `pose/filter_state` ([hbba_lite/SetOnOffFilterState](../../hbba_lite/srv/SetOnOffFilterState.srv)): The HBBA filter +- `pose/filter_state` ([hbba_lite_srvs/SetOnOffFilterState](../../utils/hbba_lite/hbba_lite_srvs/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the behavior. diff --git a/ros/behaviors/gesture/package.xml b/ros/behaviors/gesture/package.xml index 8db55954..9a3ffc9e 100644 --- a/ros/behaviors/gesture/package.xml +++ b/ros/behaviors/gesture/package.xml @@ -1,74 +1,29 @@ - + + gesture 0.0.0 The gesture package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rclpy + daemon_ros_client + std_msgs + hbba_lite + t_top + behavior_msgs - - - - TODO + rosidl_default_runtime + ros2launch + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - hbba_lite - rospy - std_msgs - t_top - message_generation - hbba_lite - rospy - std_msgs - t_top - message_generation - hbba_lite - rospy - std_msgs - t_top - message_generation - - - - - + ament_cmake diff --git a/ros/behaviors/gesture/scripts/gesture_node.py b/ros/behaviors/gesture/scripts/gesture_node.py index 8b1902a6..2a46d322 100755 --- a/ros/behaviors/gesture/scripts/gesture_node.py +++ b/ros/behaviors/gesture/scripts/gesture_node.py @@ -1,9 +1,10 @@ #!/usr/bin/env python3 -import threading +import rclpy +import rclpy.node +import rclpy.executors -import rospy -from gesture.msg import GestureName, Done +from behavior_msgs.msg import GestureName, Done from t_top import MovementCommands @@ -17,28 +18,27 @@ MOVE_SAD_TIMEOUT = 5 -class GestureNode: +class GestureNode(rclpy.node.Node): def __init__(self): - self._simulation = rospy.get_param('~simulation') + super().__init__('gesture_node') - self._gesture_lock = threading.Lock() - self._movement_commands = MovementCommands(self._simulation, namespace='gesture') + self._simulation = self.declare_parameter('simulation', False).get_parameter_value().bool_value + self._movement_commands = MovementCommands(self, self._simulation, namespace='gesture') - self._done_pub = rospy.Publisher('gesture/done', Done, queue_size=5) - self._gesture_sub = rospy.Subscriber('gesture/name', GestureName, self._on_gesture_cb) + self._done_pub = self.create_publisher(Done, 'gesture/done', 5) + self._gesture_sub = self.create_subscription(GestureName, 'gesture/name', self._on_gesture_cb, 5) def _on_gesture_cb(self, msg): - with self._gesture_lock: - if self._movement_commands.is_filtering_all_messages: - return + if self._movement_commands.is_filtering_all_messages: + return - try: - ok = self._execute_gesture(msg.name) - except TimeoutError: - rospy.logerr(f'The {msg.name} gesture has timed out.') - ok = False + try: + ok = self._execute_gesture(msg.name) + except TimeoutError: + self.get_logger().error(f'The {msg.name} gesture has timed out.') + ok = False - self._done_pub.publish(Done(id=msg.id, ok=ok)) + self._done_pub.publish(Done(id=msg.id, ok=ok)) def _execute_gesture(self, name): if name == 'yes': @@ -61,23 +61,30 @@ def _execute_gesture(self, name): elif name == 'sad': self._movement_commands.move_head_to_sad(timeout=MOVE_SAD_TIMEOUT) else: - rospy.logerr(f'Invalid gesture name ({name})') + self.get_logger().error(f'Invalid gesture name ({name})') return False return True def run(self): - rospy.spin() + executor = rclpy.executors.MultiThreadedExecutor(num_threads=2) + executor.add_node(self) + executor.spin() def main(): - rospy.init_node('gesture_node') + rclpy.init() gesture_node = GestureNode() - gesture_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + gesture_node.run() + except KeyboardInterrupt: pass + finally: + gesture_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/behaviors/led_animations/CMakeLists.txt b/ros/behaviors/led_animations/CMakeLists.txt index ef6f5494..51b9bd2b 100644 --- a/ros/behaviors/led_animations/CMakeLists.txt +++ b/ros/behaviors/led_animations/CMakeLists.txt @@ -1,211 +1,36 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(led_animations) -## Compile as C++11, supported in ROS Kinetic and newer -# add_compile_options(-std=c++11) - -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - daemon_ros_client - hbba_lite - message_generation - rospy - geometry_msgs - sensor_msgs -) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -add_message_files( - FILES - Animation.msg - Done.msg -) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -generate_messages( - DEPENDENCIES - daemon_ros_client - geometry_msgs - sensor_msgs -) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( -# INCLUDE_DIRS include -# LIBRARIES led_animations -# CATKIN_DEPENDS daemon_ros_client hbba_lite message_generation rospy -# DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( -# include - ${catkin_INCLUDE_DIRS} -) - -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/led_animations.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -# add_executable(${PROJECT_NAME}_node src/led_animations_node.cpp) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -# target_link_libraries(${PROJECT_NAME}_node -# ${catkin_LIBRARIES} -# ) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -catkin_install_python(PROGRAMS +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclpy REQUIRED) +find_package(daemon_ros_client REQUIRED) +find_package(std_msgs REQUIRED) +find_package(hbba_lite REQUIRED) +find_package(t_top REQUIRED) +find_package(behavior_msgs REQUIRED) + +# Python Librairies +ament_python_install_package(${PROJECT_NAME}) + +# Python Nodes +install(PROGRAMS scripts/led_animations_node.py - DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} + DESTINATION lib/${PROJECT_NAME} ) -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_led_animations.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() - -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/behaviors/led_animations/README.md b/ros/behaviors/led_animations/README.md index 37f56cd1..156a57f4 100644 --- a/ros/behaviors/led_animations/README.md +++ b/ros/behaviors/led_animations/README.md @@ -8,16 +8,19 @@ This folder contains the node to perform animations with the LED strip. This node performs animations with the LED strip. +#### Parameters +- `period_s` (double): The period in seconds of the animation timer. The default value is 0.0333. + #### Subscribed Topics -- `led_animations/name` ([led_animations/Animation](msg/Animation.msg)): The animation parameters. +- `led_animations/name` ([behavior_msgs/Animation](../behavior_msgs/msg/Animation.msg)): The animation parameters. #### Published Topics - `led_animations/set_led_colors` ([daemon_ros_client/LedColors](../../daemon_ros_client/msg/LedColors.msg)): The LED colors. -- `led_animations/done` ([led_animations/Done](msg/Done.msg)): Indicates that the animation is finished. +- `led_animations/done` ([led_animations/Done](../behavior_msgs/msg/Done.msg)): Indicates that the animation is finished. #### Services -- `set_led_colors/filter_state` ([hbba_lite/SetOnOffFilterState](../../hbba_lite/srv/SetOnOffFilterState.srv)): The HBBA filter +- `set_led_colors/filter_state` ([hbba_lite_srvs/SetOnOffFilterState](../../utils/hbba_lite/hbba_lite_srvs/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the behavior. diff --git a/ros/behaviors/talk/src/talk/__init__.py b/ros/behaviors/led_animations/led_animations/__init__.py similarity index 100% rename from ros/behaviors/talk/src/talk/__init__.py rename to ros/behaviors/led_animations/led_animations/__init__.py diff --git a/ros/behaviors/led_animations/src/led_animations/lib_led_animations.py b/ros/behaviors/led_animations/led_animations/lib_led_animations.py similarity index 99% rename from ros/behaviors/led_animations/src/led_animations/lib_led_animations.py rename to ros/behaviors/led_animations/led_animations/lib_led_animations.py index e2b91f6f..164f7278 100644 --- a/ros/behaviors/led_animations/src/led_animations/lib_led_animations.py +++ b/ros/behaviors/led_animations/led_animations/lib_led_animations.py @@ -1,6 +1,5 @@ from abc import ABC, abstractmethod import random -from typing import List import numpy as np diff --git a/ros/behaviors/led_animations/msg/Done.msg b/ros/behaviors/led_animations/msg/Done.msg deleted file mode 100644 index dae3f6dd..00000000 --- a/ros/behaviors/led_animations/msg/Done.msg +++ /dev/null @@ -1,2 +0,0 @@ -uint64 id -bool ok diff --git a/ros/behaviors/led_animations/package.xml b/ros/behaviors/led_animations/package.xml index 0f370122..07d6b83c 100644 --- a/ros/behaviors/led_animations/package.xml +++ b/ros/behaviors/led_animations/package.xml @@ -1,75 +1,29 @@ - + + led_animations 0.0.0 The led_animations package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rclpy + daemon_ros_client + std_msgs + hbba_lite + t_top + behavior_msgs - - - - TODO + rosidl_default_runtime + ros2launch + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - daemon_ros_client - hbba_lite - message_generation - rospy - geometry_msgs - sensor_msgs - daemon_ros_client - hbba_lite - rospy - geometry_msgs - sensor_msgs - daemon_ros_client - hbba_lite - rospy - geometry_msgs - sensor_msgs - - - - - + ament_cmake diff --git a/ros/behaviors/led_animations/scripts/led_animations_node.py b/ros/behaviors/led_animations/scripts/led_animations_node.py old mode 100644 new mode 100755 index 1e662fbd..61eb0be2 --- a/ros/behaviors/led_animations/scripts/led_animations_node.py +++ b/ros/behaviors/led_animations/scripts/led_animations_node.py @@ -1,10 +1,14 @@ -import json +#!/usr/bin/env python3 + +import traceback import math -import rospy +import rclpy +import rclpy.node +from rclpy.duration import Duration from daemon_ros_client.msg import LedColors -from led_animations.msg import Animation, Done +from behavior_msgs.msg import LedAnimation as LedAnimationMsg, Done import hbba_lite @@ -18,22 +22,25 @@ led_color.blue = 0 -class LedAnimationsNode: +class LedAnimationsNode(rclpy.node.Node): def __init__(self): - self._period_s = rospy.get_param('~period_s', 0.0333) + super().__init__('led_animations_node') + + self._period_s = self.declare_parameter('period_s', 0.0333).get_parameter_value().double_value self._timer = None self._timer_msg_id = -1 - self._timer_start_time_s = 0.0 - self._timer_duration_s = 0.0 + self._timer_start_time = None + self._timer_finite = None + self._timer_duration = None self._timer_animation = None - self._led_colors_pub = hbba_lite.OnOffHbbaPublisher('led_animations/set_led_colors', LedColors, queue_size=1, + self._led_colors_pub = hbba_lite.OnOffHbbaPublisher(self, LedColors, 'led_animations/set_led_colors', 1, state_service_name='set_led_colors/filter_state') self._led_colors_pub.on_filter_state_changing(self._hbba_filter_state_cb) - self._done_pub = rospy.Publisher('led_animations/done', Done, queue_size=5) - self._led_emotion_sub = rospy.Subscriber('led_animations/animation', Animation, self._animation_cb, queue_size=1) + self._done_pub = self.create_publisher(Done, 'led_animations/done', 5) + self._led_emotion_sub = self.create_subscription(LedAnimationMsg, 'led_animations/animation', self._animation_cb, 1) def _hbba_filter_state_cb(self, publish_forced, previous_is_filtering_all_messages, new_is_filtering_all_messages): if not previous_is_filtering_all_messages and new_is_filtering_all_messages: @@ -46,49 +53,56 @@ def _animation_cb(self, msg): try: animation = LedAnimation.from_name(msg.name, self._period_s, msg.speed, msg.colors) + self._start_timer(msg.id, animation, msg.duration_s) except Exception as e: - rospy.logerr(f'Unable to instantiate the LED animation ({e})') + tb = traceback.format_exc() + self.get_logger().error(f'Unable to instantiate the LED animation ({e}): {tb}') self._done_pub.publish(Done(id=msg.id, ok=False)) - self._start_timer(msg.id, animation, msg.duration_s) def _stop_timer(self): if self._timer is not None: - self._timer.shutdown() + self.destroy_timer(self._timer) self._timer = None self._timer_msg_id = -1 - self._timer_start_time_s = 0.0 - self._timer_duration_s = 0.0 + self._timer_start_time = None + self._timer_duration = None self._timer_animation = None def _start_timer(self, id, animation, duration_s): self._stop_timer() self._timer_msg_id = id - self._timer_start_time_s = rospy.get_time() - self._timer_duration_s = duration_s + self._timer_start_time = self.get_clock().now() + self._timer_finite = math.isfinite(duration_s) + self._timer_duration = Duration(seconds=duration_s) if self._timer_finite else None self._timer_animation = animation - self._timer = rospy.Timer(rospy.Duration(self._period_s), self._timer_cb) + self._timer = self.create_timer(self._period_s, self._timer_cb) - def _timer_cb(self, timer_event): - if rospy.get_time() - self._timer_start_time_s > self._timer_duration_s: + def _timer_cb(self): + if not self._timer_finite or self.get_clock().now() - self._timer_start_time < self._timer_duration: + self._led_colors_pub.publish(self._timer_animation.update()) + else: self._led_colors_pub.publish(NONE_LED_COLORS) self._done_pub.publish(Done(id=self._timer_msg_id, ok=True)) self._stop_timer() - else: - self._led_colors_pub.publish(self._timer_animation.update()) def run(self): - rospy.spin() + rclpy.spin(self) def main(): - rospy.init_node('led_animations_node') + rclpy.init() led_animations_node = LedAnimationsNode() - led_animations_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + led_animations_node.run() + except KeyboardInterrupt: pass + finally: + led_animations_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/behaviors/led_animations/setup.py b/ros/behaviors/led_animations/setup.py deleted file mode 100644 index ccbcc699..00000000 --- a/ros/behaviors/led_animations/setup.py +++ /dev/null @@ -1,12 +0,0 @@ -## ! DO NOT MANUALLY INVOKE THIS setup.py, USE CATKIN INSTEAD - -from setuptools import setup -from catkin_pkg.python_setup import generate_distutils_setup - -# fetch values from package.xml -setup_args = generate_distutils_setup( - packages=['led_animations'], - package_dir={'': 'src'}, -) - -setup(**setup_args) diff --git a/ros/behaviors/led_emotions/CMakeLists.txt b/ros/behaviors/led_emotions/CMakeLists.txt index 9d019e95..91fea45f 100644 --- a/ros/behaviors/led_emotions/CMakeLists.txt +++ b/ros/behaviors/led_emotions/CMakeLists.txt @@ -1,207 +1,39 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(led_emotions) -## Compile as C++11, supported in ROS Kinetic and newer -# add_compile_options(-std=c++11) - -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - daemon_ros_client - hbba_lite - rospy - std_msgs -) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -# add_message_files( -# FILES -# Message1.msg -# Message2.msg -# ) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -# generate_messages( -# DEPENDENCIES -# std_msgs # Or other packages containing msgs -# ) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( -# INCLUDE_DIRS include -# LIBRARIES led_emotions -# CATKIN_DEPENDS daemon_ros_client hbba_lite rospy -# DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( -# include - ${catkin_INCLUDE_DIRS} -) - -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/led_emotions.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -# add_executable(${PROJECT_NAME}_node src/led_emotions_node.cpp) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -# target_link_libraries(${PROJECT_NAME}_node -# ${catkin_LIBRARIES} -# ) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -catkin_install_python(PROGRAMS +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclpy REQUIRED) +find_package(daemon_ros_client REQUIRED) +find_package(std_msgs REQUIRED) +find_package(hbba_lite REQUIRED) +find_package(t_top REQUIRED) + +# Python Nodes +install(PROGRAMS scripts/led_emotions_node.py - DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} + DESTINATION lib/${PROJECT_NAME} ) -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) +# Install the pattern files +install(DIRECTORY led_patterns DESTINATION share/${PROJECT_NAME}) -############# -## Testing ## -############# -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_led_emotions.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() +# Launch files +install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}) -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/behaviors/led_emotions/README.md b/ros/behaviors/led_emotions/README.md index 177333c3..924a85eb 100644 --- a/ros/behaviors/led_emotions/README.md +++ b/ros/behaviors/led_emotions/README.md @@ -10,11 +10,12 @@ This node makes T-Top express emotions with it LED strip. #### Parameters +- `period_s` (double): The period in second of the animation timer. The default value is 0.0333. - `led_patterns_file` (string): The file path containing the LED patterns #### Subscribed Topics -- `led_emotions/name` ([std_msgs/String](http://docs.ros.org/en/noetic/api/std_msgs/html/msg/String.html)): The emotion names. +- `led_emotions/name` ([std_msgs/String](https://docs.ros.org/en/humble/p/std_msgs/interfaces/msg/String.html)): The emotion names. #### Published Topics @@ -22,5 +23,5 @@ This node makes T-Top express emotions with it LED strip. #### Services -- `set_led_colors/filter_state` ([hbba_lite/SetOnOffFilterState](../../hbba_lite/srv/SetOnOffFilterState.srv)): The HBBA filter +- `set_led_colors/filter_state` ([hbba_lite_srvs/SetOnOffFilterState](../../utils/hbba_lite/hbba_lite_srvs/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the behavior. diff --git a/ros/behaviors/led_emotions/launch/test_led_emotions.launch.xml b/ros/behaviors/led_emotions/launch/test_led_emotions.launch.xml new file mode 100644 index 00000000..cbfd7317 --- /dev/null +++ b/ros/behaviors/led_emotions/launch/test_led_emotions.launch.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ros/behaviors/led_emotions/led_patterns.json b/ros/behaviors/led_emotions/led_patterns/led_patterns.json similarity index 100% rename from ros/behaviors/led_emotions/led_patterns.json rename to ros/behaviors/led_emotions/led_patterns/led_patterns.json diff --git a/ros/behaviors/led_emotions/package.xml b/ros/behaviors/led_emotions/package.xml index 2ba432bc..13016a47 100644 --- a/ros/behaviors/led_emotions/package.xml +++ b/ros/behaviors/led_emotions/package.xml @@ -1,71 +1,29 @@ - + + led_emotions 0.0.0 The led_emotions package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rosidl_default_generators + rclpy + daemon_ros_client + std_msgs + hbba_lite + t_top - - - - TODO + rosidl_default_runtime + ros2launch + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - daemon_ros_client - hbba_lite - rospy - std_msgs - daemon_ros_client - hbba_lite - rospy - std_msgs - daemon_ros_client - hbba_lite - rospy - std_msgs - - - - - + ament_cmake diff --git a/ros/behaviors/led_emotions/scripts/led_emotions_node.py b/ros/behaviors/led_emotions/scripts/led_emotions_node.py old mode 100644 new mode 100755 index 5250cd68..a66d6162 --- a/ros/behaviors/led_emotions/scripts/led_emotions_node.py +++ b/ros/behaviors/led_emotions/scripts/led_emotions_node.py @@ -1,7 +1,10 @@ +#!/usr/bin/env python3 + import json import math -import rospy +import rclpy +import rclpy.node from std_msgs.msg import String from daemon_ros_client.msg import LedColors @@ -25,21 +28,25 @@ def __init__(self, red, green, blue, period_s, ratio): self.ratio = ratio -class LedEmotionsNode: +class LedEmotionsNode(rclpy.node.Node): def __init__(self): - self._period_s = rospy.get_param('~period_s', 0.0333) - with open(rospy.get_param('~led_patterns_file'), 'r') as f: + super().__init__('led_emotions_node') + + self._period_s = self.declare_parameter('period_s', 0.0333).get_parameter_value().double_value + led_patterns_file = self.declare_parameter('led_patterns_file', '').get_parameter_value().string_value + + with open(led_patterns_file, 'r') as f: self._led_patterns_by_emotion_name = self._load_led_patterns(json.load(f)) self._timer = None self._timer_time_s = 0 self._timer_pattern = None - self._led_colors_pub = hbba_lite.OnOffHbbaPublisher('led_emotions/set_led_colors', LedColors, queue_size=1, + self._led_colors_pub = hbba_lite.OnOffHbbaPublisher(self, LedColors, 'led_emotions/set_led_colors', 1, state_service_name='set_led_colors/filter_state') self._led_colors_pub.on_filter_state_changing(self._hbba_filter_state_cb) - self._led_emotion_sub = rospy.Subscriber('led_emotions/name', String, self._emotion_cb, queue_size=1) + self._led_emotion_sub = self.create_subscription(String, 'led_emotions/name', self._emotion_cb, 1) def _load_led_patterns(self, json_dict): @@ -62,21 +69,22 @@ def _emotion_cb(self, msg): return if msg.data not in self._led_patterns_by_emotion_name: - rospy.logerr(f'Invalid emotion name ({msg.data})') - self._start_timer(self._led_patterns_by_emotion_name[msg.data]) + self.get_logger().error(f'Invalid emotion name ({msg.data})') + else: + self._start_timer(self._led_patterns_by_emotion_name[msg.data]) def _stop_timer(self): if self._timer is not None: - self._timer.shutdown() + self.destroy_timer(self._timer) self._timer = None def _start_timer(self, pattern): self._stop_timer() self._timer_time_s = 0 self._timer_pattern = pattern - self._timer = rospy.Timer(rospy.Duration(self._period_s), self._timer_cb) + self._timer = self.create_timer(self._period_s, self._timer_cb) - def _timer_cb(self, timer_event): + def _timer_cb(self): self._timer_time_s += self._period_s if self._timer_time_s > self._timer_pattern.period_s: self._timer_time_s -= self._timer_pattern.period_s @@ -107,17 +115,22 @@ def _get_brightness(self, t, T, ratio): return 0 def run(self): - rospy.spin() + rclpy.spin(self) def main(): - rospy.init_node('led_emotions_node') + rclpy.init() led_emotions_node = LedEmotionsNode() - led_emotions_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + led_emotions_node.run() + except KeyboardInterrupt: pass + finally: + led_emotions_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/behaviors/piper_ros/CMakeLists.txt b/ros/behaviors/piper_ros/CMakeLists.txt index 948762bd..6e493b0e 100644 --- a/ros/behaviors/piper_ros/CMakeLists.txt +++ b/ros/behaviors/piper_ros/CMakeLists.txt @@ -1,18 +1,20 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(piper_ros) -## Compile as C++11, supported in ROS Kinetic and newer -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - message_generation - roscpp - roslib -) +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() ## System dependencies are found with CMake's conventions # External Dependencies @@ -34,12 +36,11 @@ link_directories(${CMAKE_BINARY_DIR}/install/fmt/lib) # ******* eSpeak NG dependency ******* -set(ESPEAK_NG_DIR "${CMAKE_BINARY_DIR}/install/espeak-ng") ExternalProject_Add( espeak_ng_external PREFIX "${CMAKE_CURRENT_BINARY_DIR}/espeak-ng" URL "https://github.com/rhasspy/espeak-ng/archive/refs/tags/2023.9.7-4.zip" - CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${ESPEAK_NG_DIR} + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX} CMAKE_ARGS -DUSE_ASYNC:BOOL=OFF CMAKE_ARGS -DBUILD_SHARED_LIBS:BOOL=ON CMAKE_ARGS -DUSE_MBROLA:BOOL=OFF @@ -50,9 +51,9 @@ ExternalProject_Add( CMAKE_ARGS -DEXTRA_cmn:BOOL=ON CMAKE_ARGS -DEXTRA_ru:BOOL=ON ) -include_directories(${CMAKE_BINARY_DIR}/install/espeak-ng/include) -link_directories(${CMAKE_BINARY_DIR}/install/espeak-ng/lib) -add_compile_definitions(ESPEAK_NG_DATA_PATH="${CMAKE_BINARY_DIR}/install/espeak-ng/share/espeak-ng-data") +include_directories(${CMAKE_INSTALL_PREFIX}/include) +link_directories(${CMAKE_INSTALL_PREFIX}/lib) +add_compile_definitions(ESPEAK_NG_DATA_PATH="${CMAKE_INSTALL_PREFIX}/share/espeak-ng-data") # ******* ONNX Runtime dependency ******* @@ -129,192 +130,23 @@ if (NOT EXISTS ${CMAKE_BINARY_DIR}/piper-${PIPER_TAG}/CMakeLists.txt) endif() include_directories(${CMAKE_BINARY_DIR}/piper-${PIPER_TAG}/src/cpp) - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -# add_message_files( -# FILES -# Message1.msg -# Message2.msg -# ) - -## Generate services in the 'srv' folder -add_service_files( - FILES - GenerateSpeechFromText.srv -) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -generate_messages() - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( -# INCLUDE_DIRS include -# LIBRARIES piper_ros -# CATKIN_DEPENDS message_generation roscpp -# DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( -# include - ${catkin_INCLUDE_DIRS} -) - -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/piper_ros.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclcpp REQUIRED) +find_package(behavior_srvs REQUIRED) +find_package(ament_index_cpp REQUIRED) ## Declare a C++ executable ## With catkin_make all packages are built within a single CMake context ## The recommended prefix ensures that target names across packages don't collide +# C++ Nodes add_executable(piper_node src/piper_node.cpp ${CMAKE_BINARY_DIR}/piper-${PIPER_TAG}/src/cpp/piper.cpp) -add_dependencies(piper_node fmt_external) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -target_link_libraries(piper_node - ${catkin_LIBRARIES} - piper_phonemize - fmt - spdlog - ${ONNXRUNTIME_LIBRARIES} -) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -# catkin_install_python(PROGRAMS -# scripts/my_python_script -# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# +ament_target_dependencies(piper_node rclcpp behavior_srvs ament_index_cpp) +target_link_libraries(piper_node piper_phonemize fmt spdlog ${ONNXRUNTIME_LIBRARIES}) +install(TARGETS piper_node DESTINATION lib/${PROJECT_NAME}) +add_dependencies(piper_node fmt_external espeak_ng_external) -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_piper_ros.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() +# Install models +install(DIRECTORY models DESTINATION share/${PROJECT_NAME}) -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/behaviors/piper_ros/README.md b/ros/behaviors/piper_ros/README.md index 126e0a0d..69f0a8d2 100644 --- a/ros/behaviors/piper_ros/README.md +++ b/ros/behaviors/piper_ros/README.md @@ -11,9 +11,9 @@ This node generates speech files with [Piper](https://github.com/rhasspy/piper). #### Parameters -- `use_gpu_if_available` (bool): Indicates whether to use the GPU or not. +- `use_gpu_if_available` (bool): Indicates whether to use the GPU or not. The default value is false. #### Services -- `piper/generate_speech_from_text` ([piper_ros/GenerateSpeechFromText](srv/GenerateSpeechFromText.srv)): +- `piper/generate_speech_from_text` ([behavior_srvs/GenerateSpeechFromText](../behavior_srvs/srv/GenerateSpeechFromText.srv)): The service to generate speech files. diff --git a/ros/behaviors/piper_ros/package.xml b/ros/behaviors/piper_ros/package.xml index 0bd92bfe..476152c5 100644 --- a/ros/behaviors/piper_ros/package.xml +++ b/ros/behaviors/piper_ros/package.xml @@ -1,63 +1,26 @@ - + + piper_ros 0.0.0 The piper_ros package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rclcpp + ament_index_cpp + behavior_srvs - - - - TODO + rosidl_default_runtime + ros2launch + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - message_generation - roscpp - roscpp - roscpp - - - - - + ament_cmake diff --git a/ros/behaviors/piper_ros/src/piper_node.cpp b/ros/behaviors/piper_ros/src/piper_node.cpp index 7c0ca43a..882163cb 100644 --- a/ros/behaviors/piper_ros/src/piper_node.cpp +++ b/ros/behaviors/piper_ros/src/piper_node.cpp @@ -1,7 +1,8 @@ -#include +#include -#include -#include +#include + +#include #include @@ -53,12 +54,11 @@ std::optional genderFromString(const std::string& str) } -class PiperNode +class PiperNode : public rclcpp::Node { bool m_useGpuIfAvailable; - ros::NodeHandle m_nodeHandle; - ros::ServiceServer m_generateSpeechFromTextService; + rclcpp::Service::SharedPtr m_generateSpeechFromTextService; piper::PiperConfig m_piperConfig; piper::Voice m_englishFemaleVoice; @@ -67,8 +67,10 @@ class PiperNode piper::Voice m_frenchMaleVoice; public: - explicit PiperNode(bool useGpuIfAvailable) : m_useGpuIfAvailable(useGpuIfAvailable) + explicit PiperNode() : rclcpp::Node("piper_node") { + m_useGpuIfAvailable = declare_parameter("use_gpu_if_available", false); + m_piperConfig.useESpeak = true; m_piperConfig.eSpeakDataPath = ESPEAK_NG_DATA_PATH; @@ -79,19 +81,22 @@ class PiperNode piper::initialize(m_piperConfig); - - m_generateSpeechFromTextService = m_nodeHandle.advertiseService( + m_generateSpeechFromTextService = create_service( "piper/generate_speech_from_text", - &PiperNode::generateSpeechFromTextServiceCallback, - this); + [this] ( + const std::shared_ptr request, + std::shared_ptr response) + { + generateSpeechFromTextServiceCallback(request, response); + }); } - void run() { ros::spin(); } + void run() { rclcpp::spin(shared_from_this()); } private: piper::Voice loadVoice(const char* filename) { - std::string modelFolder = ros::package::getPath("piper_ros") + "/models/"; + std::string modelFolder = ament_index_cpp::get_package_share_directory("piper_ros") + "/models/"; piper::Voice voice; voice.session.options.SetInterOpNumThreads(1); @@ -109,7 +114,7 @@ class PiperNode #else if (m_useGpuIfAvailable) { - ROS_WARN("CUDA is not supported."); + RCLCPP_WARN(get_logger(), "CUDA is not supported."); } #endif @@ -124,30 +129,26 @@ class PiperNode return voice; } - bool generateSpeechFromTextServiceCallback( - piper_ros::GenerateSpeechFromText::Request& request, - piper_ros::GenerateSpeechFromText::Response& response) + void generateSpeechFromTextServiceCallback( + const std::shared_ptr request, + std::shared_ptr response) { - std::optional language = languageFromString(request.language); + std::optional language = languageFromString(request->language); if (language == std::nullopt) { - response.ok = false; - response.message = "Invalid language"; - return true; + response->ok = false; + response->message = "Invalid language"; } - std::optional gender = genderFromString(request.gender); + std::optional gender = genderFromString(request->gender); if (gender == std::nullopt) { - response.ok = false; - response.message = "Invalid gender"; - return true; + response->ok = false; + response->message = "Invalid gender"; } - generateSpeechFromText(*language, *gender, request.length_scale, request.text, request.path); - response.ok = true; - - return true; + generateSpeechFromText(*language, *gender, request->length_scale, request->text, request->path); + response->ok = true; } void generateSpeechFromText( @@ -194,19 +195,12 @@ class PiperNode int main(int argc, char** argv) { - ros::init(argc, argv, "piper_node"); + rclcpp::init(argc, argv); - ros::NodeHandle privateNodeHandle("~"); - - bool useGpuIfAvailable; - if (!privateNodeHandle.getParam("use_gpu_if_available", useGpuIfAvailable)) - { - ROS_ERROR("The parameter use_gpu_if_available is required."); - return -1; - } + auto node = std::make_shared(); + node->run(); - PiperNode node(useGpuIfAvailable); - node.run(); + rclcpp::shutdown(); return 0; } diff --git a/ros/behaviors/sound_following/CMakeLists.txt b/ros/behaviors/sound_following/CMakeLists.txt index 5f51c0e9..e70d1150 100644 --- a/ros/behaviors/sound_following/CMakeLists.txt +++ b/ros/behaviors/sound_following/CMakeLists.txt @@ -1,207 +1,33 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(sound_following) -## Compile as C++11, supported in ROS Kinetic and newer -# add_compile_options(-std=c++11) - -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - hbba_lite - rospy - t_top - odas_ros - ) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -# add_message_files( -# FILES -# Message1.msg -# Message2.msg -# ) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -# generate_messages( -# DEPENDENCIES -# geometry_msgs# std_msgs -# ) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( - # INCLUDE_DIRS include - # LIBRARIES sound_following - # CATKIN_DEPENDS geometry_msgs hbba_lite rospy std_msgs t_top tf - # DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( - # include - ${catkin_INCLUDE_DIRS} +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclpy REQUIRED) +find_package(daemon_ros_client REQUIRED) +find_package(std_msgs REQUIRED) +find_package(hbba_lite REQUIRED) +find_package(t_top REQUIRED) +find_package(odas_ros_msgs REQUIRED) + +# Python Nodes +install(PROGRAMS + scripts/sound_following_node.py + DESTINATION lib/${PROJECT_NAME} ) -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/sound_following.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -# add_executable(${PROJECT_NAME}_node src/sound_following_node.cpp) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -# target_link_libraries(${PROJECT_NAME}_node -# ${catkin_LIBRARIES} -# ) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -catkin_install_python(PROGRAMS - scripts/sound_following_node.py - DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} - ) - -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_sound_following.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() - -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/behaviors/sound_following/README.md b/ros/behaviors/sound_following/README.md index fdd72eae..2935afb1 100644 --- a/ros/behaviors/sound_following/README.md +++ b/ros/behaviors/sound_following/README.md @@ -10,32 +10,32 @@ This node makes T-Top follow the loudest sound. #### Parameters -- `simulation` (bool): Indicates if it's used in the simulation. -- `control_frequency` (double): The frequency at which the pose messages are sent. -- `torso_control_alpha` (double): The low-pass filter parameter for the torso pose. -- `head_control_alpha` (double): The low-pass filter parameter for the head pose. -- `head_enabled` (bool): Indicates if the head will move. -- `min_head_pitch_rad` (double): The minimum pitch angle in radian of the head. -- `max_head_pitch_rad` (double): The maximum pitch angle in radian of the head. -- `min_activity` (double): The minimum activity level to consider the sound source valid. -- `min_valid_source_pitch_rad` (double): The minimum pitch angle in radian to consider the sound source valid. -- `max_valid_source_pitch_rad` (double): The maximum pitch angle in radian to consider the sound source valid. -- `direction_frame_id` (string): The audio analysis frame id. +- `simulation` (bool): Indicates if it's used in the simulation. The default value is false. +- `control_frequency` (double): The frequency at which the pose messages are sent. The default value is 30.0. +- `torso_control_alpha` (double): The low-pass filter parameter for the torso pose. The default value is 0.2. +- `head_control_alpha` (double): The low-pass filter parameter for the head pose. The default value is 0.2. +- `head_enabled` (bool): Indicates if the head will move. The default value is false. +- `min_head_pitch_rad` (double): The minimum pitch angle in radian of the head. The default value is -0.35. +- `max_head_pitch_rad` (double): The maximum pitch angle in radian of the head. The default value is 0.35. +- `min_activity` (double): The minimum activity level to consider the sound source valid. The default value is 0.1. +- `min_valid_source_pitch_rad` (double): The minimum pitch angle in radian to consider the sound source valid. The default value is -1.4. +- `max_valid_source_pitch_rad` (double): The maximum pitch angle in radian to consider the sound source valid. The default value is 1.4. +- `direction_frame_id` (string): The audio analysis frame id. The default value is odas. #### Subscribed Topics - `daemon/motor_status` ([daemon_ros_client/MotorStatus](../../daemon_ros_client/msg/MotorStatus.msg)): The motor status. -- `sst` ([odas_ros/OdasSstArrayStamped](https://github.com/introlab/odas_ros/blob/main/msg/OdasSstArrayStamped.msg)): +- `sst` ([odas_ros_msgs/OdasSstArrayStamped](https://github.com/introlab/odas_ros/blob/ros2/odas_ros_msgs/msg/OdasSstArrayStamped.msg)): The sound source tracking information. #### Published Topics -- `sound_following/set_head_pose` ([geometry_msgs/PoseStamped](http://docs.ros.org/en/noetic/api/geometry_msgs/html/msg/PoseStamped.html)): +- `sound_following/set_head_pose` ([geometry_msgs/PoseStamped](https://docs.ros.org/en/humble/p/geometry_msgs/interfaces/msg/PoseStamped.html)): The head pose. -- `sound_following/set_torso_orientation` ([std_msgs/Float32](http://docs.ros.org/en/noetic/api/std_msgs/html/msg/Float32.html)): The +- `sound_following/set_torso_orientation` ([std_msgs/Float32](https://docs.ros.org/en/humble/p/std_msgs/interfaces/msg/Float32.html)): The torso orientation. #### Services -- `pose/filter_state` ([hbba_lite/SetOnOffFilterState](../../hbba_lite/srv/SetOnOffFilterState.srv)): The HBBA filter +- `pose/filter_state` ([hbba_lite_srvs/SetOnOffFilterState](../../utils/hbba_lite/hbba_lite_srvs/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the behavior. diff --git a/ros/behaviors/sound_following/package.xml b/ros/behaviors/sound_following/package.xml index 0c3a0ac3..ba74ab03 100644 --- a/ros/behaviors/sound_following/package.xml +++ b/ros/behaviors/sound_following/package.xml @@ -1,71 +1,28 @@ - + + sound_following 0.0.0 The sound_following package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rclpy + daemon_ros_client + std_msgs + hbba_lite + t_top + odas_ros_msgs - - - - TODO + rosidl_default_runtime + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - hbba_lite - rospy - t_top - odas_ros - hbba_lite - rospy - t_top - odas_ros - hbba_lite - rospy - t_top - odas_ros - - - - - + ament_cmake diff --git a/ros/behaviors/sound_following/scripts/sound_following_node.py b/ros/behaviors/sound_following/scripts/sound_following_node.py index 8efb11c7..33fcc318 100755 --- a/ros/behaviors/sound_following/scripts/sound_following_node.py +++ b/ros/behaviors/sound_following/scripts/sound_following_node.py @@ -1,10 +1,12 @@ #!/usr/bin/env python3 import math -import threading -import rospy -from odas_ros.msg import OdasSstArrayStamped +import rclpy +import rclpy.node +import rclpy.executors + +from odas_ros_msgs.msg import OdasSstArrayStamped from t_top import MovementCommands, vector_to_angles, HEAD_ZERO_Z, HEAD_POSE_PITCH_INDEX @@ -12,35 +14,38 @@ TARGET_TOLERANCE = 0.02 -class SoundFollowingNode: +class SoundFollowingNode(rclpy.node.Node): def __init__(self): - self._simulation = rospy.get_param('~simulation') - self._rate = rospy.Rate(rospy.get_param('~control_frequency')) - self._torso_control_alpha = rospy.get_param('~torso_control_alpha') - self._head_control_alpha = rospy.get_param('~head_control_alpha') - self._head_enabled = rospy.get_param('~head_enabled') - self._min_head_pitch = rospy.get_param('~min_head_pitch_rad') - self._max_head_pitch = rospy.get_param('~max_head_pitch_rad') - self._min_activity = rospy.get_param('~min_activity') - self._min_valid_source_pitch = rospy.get_param('~min_valid_source_pitch_rad') - self._max_valid_source_pitch = rospy.get_param('~max_valid_source_pitch_rad') - self._direction_frame_id = rospy.get_param('~direction_frame_id') - - self._target_lock = threading.Lock() + super().__init__('sound_following_node') + + self._simulation = self.declare_parameter('simulation', False).get_parameter_value().bool_value + self._control_frequency = self.declare_parameter('control_frequency', 30.0).get_parameter_value().double_value + self._torso_control_alpha = self.declare_parameter('torso_control_alpha', 0.2).get_parameter_value().double_value + self._head_control_alpha = self.declare_parameter('head_control_alpha', 0.2).get_parameter_value().double_value + self._head_enabled = self.declare_parameter('head_enabled', False).get_parameter_value().bool_value + self._min_head_pitch = self.declare_parameter('min_head_pitch_rad', -0.35).get_parameter_value().double_value + self._max_head_pitch = self.declare_parameter('max_head_pitch_rad', 0.35).get_parameter_value().double_value + self._min_activity = self.declare_parameter('min_activity', 0.1).get_parameter_value().double_value + self._min_valid_source_pitch = self.declare_parameter('min_valid_source_pitch_rad', -1.4).get_parameter_value().double_value + self._max_valid_source_pitch = self.declare_parameter('max_valid_source_pitch_rad', 1.4).get_parameter_value().double_value + self._direction_frame_id = self.declare_parameter('direction_frame_id', 'odas').get_parameter_value().string_value + self._target_torso_yaw = None self._target_head_pitch = None - self._movement_commands = MovementCommands(self._simulation, namespace='sound_following') - self._sst_sub = rospy.Subscriber('sst', OdasSstArrayStamped, self._sst_cb, queue_size=10) + self._movement_commands = MovementCommands(self, self._simulation, namespace='sound_following') + self._sst_sub = self.create_subscription(OdasSstArrayStamped, 'sst', self._sst_cb, 10) + + self._timer = self.create_timer(1 / self._control_frequency, self._timer_callback) def _sst_cb(self, sst): if self._movement_commands.is_filtering_all_messages: return if len(sst.sources) > 1: - rospy.logerr(f'Invalid sst (len(sst.sources)={len(sst.sources)})') + self.get_logger().error(f'Invalid sst (len(sst.sources)={len(sst.sources)})') return if sst.header.frame_id != self._direction_frame_id: - rospy.logerr(f'Invalid direction frame id ({sst.header.frame_id} != {self._direction_frame_id})') + self.get_logger().error(f'Invalid direction frame id ({sst.header.frame_id} != {self._direction_frame_id})') return if len(sst.sources) == 0 or sst.sources[0].activity < self._min_activity: return @@ -49,27 +54,27 @@ def _sst_cb(self, sst): if pitch < self._min_valid_source_pitch or pitch > self._max_valid_source_pitch: return - with self._target_lock: - self._target_torso_yaw = yaw - self._target_head_pitch = None if pitch is None else max(self._min_head_pitch, min(pitch, self._max_head_pitch)) + self._target_torso_yaw = yaw + self._target_head_pitch = None if pitch is None else max(self._min_head_pitch, min(pitch, self._max_head_pitch)) - def run(self): - while not rospy.is_shutdown(): - self._rate.sleep() - if self._movement_commands.is_filtering_all_messages: - continue + def _timer_callback(self): + if self._movement_commands.is_filtering_all_messages: + return - self._update_torso() - if self._head_enabled: - self._update_head() + self._update_torso() + if self._head_enabled: + self._update_head() + + def run(self): + executor = rclpy.executors.MultiThreadedExecutor(num_threads=2) + executor.add_node(self) + executor.spin() def _update_torso(self): - with self._target_lock: - target_torso_yaw = self._target_torso_yaw - if target_torso_yaw is None: + if self._target_torso_yaw is None: return - distance = target_torso_yaw - self._movement_commands.current_torso_pose + distance = self._target_torso_yaw - self._movement_commands.current_torso_pose if abs(distance) < TARGET_TOLERANCE: return @@ -82,27 +87,30 @@ def _update_torso(self): self._movement_commands.move_torso(pose) def _update_head(self): - with self._target_lock: - target_head_pitch = self._target_head_pitch - if target_head_pitch is None: + if self._target_head_pitch is None: return current_pitch = self._movement_commands.current_head_pose[HEAD_POSE_PITCH_INDEX] - if abs(target_head_pitch - current_pitch) < TARGET_TOLERANCE: + if abs(self._target_head_pitch - current_pitch) < TARGET_TOLERANCE: return - pitch = self._head_control_alpha * target_head_pitch + (1 - self._head_control_alpha) * current_pitch + pitch = self._head_control_alpha * self._target_head_pitch + (1 - self._head_control_alpha) * current_pitch self._movement_commands.move_head([0, 0, HEAD_ZERO_Z, 0, pitch, 0]) def main(): - rospy.init_node('sound_following_node') + rclpy.init() sound_following_node = SoundFollowingNode() - sound_following_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + sound_following_node.run() + except KeyboardInterrupt: pass + finally: + sound_following_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/behaviors/sound_object_person_following/.gitignore b/ros/behaviors/sound_object_person_following/.gitignore deleted file mode 100644 index a2a4546e..00000000 --- a/ros/behaviors/sound_object_person_following/.gitignore +++ /dev/null @@ -1 +0,0 @@ -camera_3d_calibration.json diff --git a/ros/behaviors/sound_object_person_following/CMakeLists.txt b/ros/behaviors/sound_object_person_following/CMakeLists.txt index 183dc689..7646ef7e 100644 --- a/ros/behaviors/sound_object_person_following/CMakeLists.txt +++ b/ros/behaviors/sound_object_person_following/CMakeLists.txt @@ -1,215 +1,47 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(sound_object_person_following) -## Compile as C++11, supported in ROS Kinetic and newer -# add_compile_options(-std=c++11) -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - geometry_msgs - hbba_lite - odas_ros - rospy - std_msgs - t_top - tf - video_analyzer - message_filters - sensor_msgs - cv_bridge -) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -# add_message_files( -# FILES -# Message1.msg -# Message2.msg -# ) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -# generate_messages( -# DEPENDENCIES -# geometry_msgs# std_msgs -# ) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( -# INCLUDE_DIRS include -# LIBRARIES sound_object_person_following -# CATKIN_DEPENDS geometry_msgs hbba_lite odas_ros rospy std_msgs t_top tf video_analyzer -# DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( -# include - ${catkin_INCLUDE_DIRS} -) - -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/sound_object_person_following.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -# add_executable(${PROJECT_NAME}_node src/sound_object_person_following_node.cpp) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -# target_link_libraries(${PROJECT_NAME}_node -# ${catkin_LIBRARIES} -# ) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -catkin_install_python(PROGRAMS +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclpy REQUIRED) +find_package(std_msgs REQUIRED) +find_package(geometry_msgs REQUIRED) +find_package(hbba_lite REQUIRED) +find_package(odas_ros_msgs REQUIRED) +find_package(t_top REQUIRED) +find_package(tf2 REQUIRED) +find_package(tf2_ros REQUIRED) +find_package(message_filters REQUIRED) +find_package(perception_msgs REQUIRED) +find_package(sensor_msgs REQUIRED) +find_package(cv_bridge REQUIRED) + +# Python Librairies +ament_python_install_package(${PROJECT_NAME}) + +# Python Nodes +install(PROGRAMS scripts/calibrate_sound_object_person_following_node.py scripts/sound_object_person_following_node.py - DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} + DESTINATION lib/${PROJECT_NAME} ) -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_sound_object_person_following.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() +# Launch files +install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}) -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/behaviors/sound_object_person_following/README.md b/ros/behaviors/sound_object_person_following/README.md index 883d9c3d..0e2db10e 100644 --- a/ros/behaviors/sound_object_person_following/README.md +++ b/ros/behaviors/sound_object_person_following/README.md @@ -10,12 +10,12 @@ This node matches the 3d camera with the 2d wide camera. #### Parameters -- `match_count` (bool): Number of match to use. +- `match_count` (bool): Number of match to use. The default value is 100. #### Subscribed Topics -- `camera_3d/color/image_raw` ([sensor_msgs/Image](http://docs.ros.org/en/noetic/api/sensor_msgs/html/msg/Image.html)): The rectified color image of the 3d camera. -- `camera_2d_wide/image_rect` ([sensor_msgs/Image](http://docs.ros.org/en/noetic/api/sensor_msgs/html/msg/Image.html)): The rectified color image of the 2d wide camera. +- `camera_3d/color/image_raw` ([sensor_msgs/Image](https://docs.ros.org/en/humble/p/sensor_msgs/interfaces/msg/Image.html)): The rectified color image of the 3d camera. +- `camera_2d_wide/image_rect` ([sensor_msgs/Image](https://docs.ros.org/en/humble/p/sensor_msgs/interfaces/msg/Image.html)): The rectified color image of the 2d wide camera. ### `sound_object_person_following_node.py` @@ -23,41 +23,40 @@ This node makes T-Top follow the loudest sound, the biggest (nearest) person and #### Parameters -- `simulation` (bool): Indicates if it's used in the simulation. -- `control_frequency` (double): The frequency at which the pose messages are sent. -- `torso_control_alpha` (double): The low-pass filter parameter for the torso pose (sound following). -- `torso_control_p_gain` (double): The controller proportional gain for the torso pose. -- `head_control_p_gain` (double): The controller proportional gain for the head pose. -- `min_head_pitch_rad` (double): The minimum pitch angle in radian of the head. -- `max_head_pitch_rad` (double): The maximum pitch angle in radian of the head. -- `object_person_follower_type` (string): The object person follower type (bounding_box or semantic_segmentation). +- `simulation` (bool): Indicates if it's used in the simulation. The default value is false. +- `control_frequency` (double): The frequency at which the pose messages are sent. The default value is 30. +- `torso_control_alpha` (double): The low-pass filter parameter for the torso pose (sound following). The default value is 0.2. +- `torso_control_p_gain` (double): The controller proportional gain for the torso pose. The default value is 0.45. +- `head_control_p_gain` (double): The controller proportional gain for the head pose. The default value is 0.45. +- `min_head_pitch_rad` (double): The minimum pitch angle in radian of the head. The default value is -0.35. +- `max_head_pitch_rad` (double): The maximum pitch angle in radian of the head. The default value is 0.35. +- `object_person_follower_type` (string): The object person follower type (bounding_box or semantic_segmentation). The default value is bounding_box. - `min_sst_activity` (double): The minimum activity level to consider the sound source valid. - `min_valid_sst_pitch` (double): The minimum pitch angle in radian to consider the sound source valid. - `max_valid_sst_pitch` (double): The maximum pitch angle in radian to consider the sound source valid. - `direction_frame_id` (string): The audio analysis frame id. -- `object_classes` (list of strings): The followed object classes. In launch files, use this syntax : - `[]`. +- `object_classes` (list of strings): The followed object classes. - `padding` (double): The padding of the person and the objects. - `target_lambda` (double): The loss scale factor centering the person. #### Subscribed Topics - `daemon/motor_status` ([daemon_ros_client/MotorStatus](../../daemon_ros_client/msg/MotorStatus.msg)): The motor status. -- `sst` ([odas_ros/OdasSstArrayStamped](https://github.com/introlab/odas_ros/blob/main/msg/OdasSstArrayStamped.msg)): +- `sst` ([odas_ros_msgs/OdasSstArrayStamped](https://github.com/introlab/odas_ros/blob/ros2/odas_ros_msgs/msg/OdasSstArrayStamped.msg)): The sound source tracking information. -- `video_analysis` ([video_analyzer/VideoAnalysis](../../perceptions/video_analyzer/msg/VideoAnalysis.msg)): The video +- `video_analysis` ([perception_msgs/VideoAnalysis](../../perceptions/perception_msgs/msg/VideoAnalysis.msg)): The video analysis containing the detected objects of the 2d wide camera. #### Published Topics -- `sound_object_person_following/set_head_pose` ([geometry_msgs/PoseStamped](http://docs.ros.org/en/noetic/api/geometry_msgs/html/msg/PoseStamped.html)): +- `sound_object_person_following/set_head_pose` ([geometry_msgs/PoseStamped](https://docs.ros.org/en/humble/p/geometry_msgs/interfaces/msg/PoseStamped.html)): The head pose. -- `sound_object_person_following/set_torso_orientation` ([std_msgs/Float32](http://docs.ros.org/en/noetic/api/std_msgs/html/msg/Float32.html)): +- `sound_object_person_following/set_torso_orientation` ([std_msgs/Float32](https://docs.ros.org/en/humble/p/std_msgs/interfaces/msg/Float32.html)): The torso orientation. #### Services -- `pose/filter_state` ([hbba_lite/SetOnOffFilterState](../../hbba_lite/srv/SetOnOffFilterState.srv)): The HBBA filter +- `pose/filter_state` ([hbba_lite_srvs/SetOnOffFilterState](../../utils/hbba_lite/hbba_lite_srvs/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the behavior. diff --git a/ros/behaviors/sound_object_person_following/launch/calibrate_sound_object_person_following.launch b/ros/behaviors/sound_object_person_following/launch/calibrate_sound_object_person_following.launch.xml similarity index 69% rename from ros/behaviors/sound_object_person_following/launch/calibrate_sound_object_person_following.launch rename to ros/behaviors/sound_object_person_following/launch/calibrate_sound_object_person_following.launch.xml index 07f514a5..bced4051 100644 --- a/ros/behaviors/sound_object_person_following/launch/calibrate_sound_object_person_following.launch +++ b/ros/behaviors/sound_object_person_following/launch/calibrate_sound_object_person_following.launch.xml @@ -1,10 +1,10 @@ - + - + diff --git a/ros/behaviors/sound_object_person_following/package.xml b/ros/behaviors/sound_object_person_following/package.xml index 182ffdb8..b2973a20 100644 --- a/ros/behaviors/sound_object_person_following/package.xml +++ b/ros/behaviors/sound_object_person_following/package.xml @@ -1,92 +1,34 @@ - + + sound_object_person_following 0.0.0 The sound_object_person_following package + Marc-Antoine Maheux + GPL-3.0 license + + ament_cmake + + rclpy + std_msgs + geometry_msgs + hbba_lite + odas_ros_msgs + t_top + tf2 + tf2_ros + message_filters + perception_msgs + sensor_msgs + cv_bridge + + rosidl_default_runtime + rosidl_interface_packages + + ament_lint_auto + ament_lint_common - - - - marc-antoine - - - - - - TODO - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - geometry_msgs - hbba_lite - odas_ros - rospy - std_msgs - t_top - tf - video_analyzer - message_filters - sensor_msgs - cv_bridge - geometry_msgs - hbba_lite - odas_ros - rospy - std_msgs - t_top - tf - video_analyzer - message_filters - sensor_msgs - cv_bridge - geometry_msgs - hbba_lite - odas_ros - rospy - std_msgs - t_top - tf - video_analyzer - message_filters - sensor_msgs - cv_bridge - - - - - + ament_cmake diff --git a/ros/behaviors/sound_object_person_following/scripts/calibrate_sound_object_person_following_node.py b/ros/behaviors/sound_object_person_following/scripts/calibrate_sound_object_person_following_node.py index 8b3002cd..0d5b2a65 100755 --- a/ros/behaviors/sound_object_person_following/scripts/calibrate_sound_object_person_following_node.py +++ b/ros/behaviors/sound_object_person_following/scripts/calibrate_sound_object_person_following_node.py @@ -1,12 +1,13 @@ #!/usr/bin/env python3 -import threading import math import numpy as np import cv2 -import rospy +import rclpy +import rclpy.node + import message_filters from cv_bridge import CvBridge @@ -17,7 +18,6 @@ MIN_MATCH_COUNT = 5 LOWES_RATIO_THRESHOLD = 0.7 -INACTIVE_SLEEP_DURATION = 1.0 class Match: @@ -32,9 +32,11 @@ def __init__(self, source_points, destination_points, self.destination_height = destination_height -class CalibrateSoundObjectPersonFollowingNode: +class CalibrateSoundObjectPersonFollowingNode(rclpy.node.Node): def __init__(self): - self._match_count = rospy.get_param('~match_count') + super().__init__('calibrate_sound_object_person_following_node') + + self._match_count = self.declare_parameter('match_count', 100).get_parameter_value().integer_value if self._match_count < 1: raise ValueError('match_count must be at least 1.') @@ -42,19 +44,17 @@ def __init__(self): self._orb = cv2.ORB_create() self._matcher = cv2.BFMatcher() - self._matches_lock = threading.Lock() self._matches = [] - self._calibration_lock = threading.Lock() try: self._calibration = Camera3dCalibration.load_json_file() except FileNotFoundError: self._calibration = None - self._camera_2d_wide_cropped_image_pub = rospy.Publisher('camera_2d_wide/cropped_image', Image, queue_size=1) + self._camera_2d_wide_cropped_image_pub = self.create_publisher(Image, 'camera_2d_wide/cropped_image', 1) - camera_3d_image_sub = message_filters.Subscriber('camera_3d/color/image_raw', Image) - camera_2d_wide_image_sub = message_filters.Subscriber('camera_2d_wide/image_rect', Image) + camera_3d_image_sub = message_filters.Subscriber(self, Image, 'camera_3d/color/image_raw') + camera_2d_wide_image_sub = message_filters.Subscriber(self, Image, 'camera_2d_wide/image_rect') self._image_ts = message_filters.ApproximateTimeSynchronizer([camera_3d_image_sub, camera_2d_wide_image_sub], 10, 0.1) self._image_ts.registerCallback(self._image_cb) @@ -62,16 +62,12 @@ def _image_cb(self, camera_3d_image_msg, camera_2d_wide_image_msg): camera_3d_image = self._cv_bridge.imgmsg_to_cv2(camera_3d_image_msg, 'bgr8') camera_2d_wide_image = self._cv_bridge.imgmsg_to_cv2(camera_2d_wide_image_msg, 'bgr8') - with self._calibration_lock: - calibration = self._calibration - - if calibration is None: + if self._calibration is None: match = self._match_images(camera_3d_image, camera_2d_wide_image) if match is not None: - with self._matches_lock: - self._matches.append(match) + self._matches.append(match) else: - self._publish_camera_2d_wide_cropped_image(camera_2d_wide_image, calibration) + self._publish_camera_2d_wide_cropped_image(camera_2d_wide_image, self._calibration) def _match_images(self, source_image, destination_image): source_keypoints, source_descriptors = self._orb.detectAndCompute(source_image, None) @@ -84,7 +80,7 @@ def _match_images(self, source_image, destination_image): good_matches.append(m) if len(good_matches) < MIN_MATCH_COUNT: - rospy.logwarn(f'Not enough ORB feature matches (count={len(good_matches)})') + self.get_logger().warn(f'Not enough ORB feature matches (count={len(good_matches)})') return None else: source_points = np.float32([source_keypoints[m.queryIdx].pt for m in good_matches]).reshape(-1,1,2) @@ -106,18 +102,16 @@ def _publish_camera_2d_wide_cropped_image(self, image, calibration): self._camera_2d_wide_cropped_image_pub.publish(self._cv_bridge.cv2_to_imgmsg(camera_2d_wide_image_cropped, 'bgr8')) def run(self): - while not rospy.is_shutdown(): - with self._matches_lock, self._calibration_lock: - match_count = len(self._matches) - has_calibration = self._calibration is not None + while rclpy.ok(): + has_calibration = self._calibration is not None - if match_count >= self._match_count and not has_calibration: + if len(self._matches) >= self._match_count and not has_calibration: self._calibration = self._find_transform(self._matches) else: if not has_calibration: - rospy.loginfo(f'Match count: {len(self._matches)}') + self.get_logger().info(f'Match count: {len(self._matches)}') - rospy.sleep(INACTIVE_SLEEP_DURATION) + rclpy.spin_once(self) def _find_transform(self, matches): source_points = np.concatenate([x.source_points for x in self._matches]) @@ -136,8 +130,8 @@ def _find_transform(self, matches): width = source_width / destination_width * scale height = source_height / destination_height * scale - rospy.loginfo('******* Results *******') - rospy.loginfo(f'scale={scale}, center_x={center_x}, center_y={center_y}, width={width}, height={height}, rotation={rotation}') + self.get_logger().info('******* Results *******') + self.get_logger().info(f'scale={scale}, center_x={center_x}, center_y={center_y}, width={width}, height={height}, rotation={rotation}') calibration = Camera3dCalibration(center_x, center_y, width, height) calibration.save_json_file() @@ -145,13 +139,18 @@ def _find_transform(self, matches): def main(): - rospy.init_node('calibrate_sound_object_person_following_node') - explore_node = CalibrateSoundObjectPersonFollowingNode() - explore_node.run() - + rclpy.init() + calibrate_sound_object_person_following_node = CalibrateSoundObjectPersonFollowingNode() -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + calibrate_sound_object_person_following_node.run() + except KeyboardInterrupt: pass + finally: + calibrate_sound_object_person_following_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/behaviors/sound_object_person_following/scripts/sound_object_person_following_node.py b/ros/behaviors/sound_object_person_following/scripts/sound_object_person_following_node.py index 393824b7..5952b0d7 100755 --- a/ros/behaviors/sound_object_person_following/scripts/sound_object_person_following_node.py +++ b/ros/behaviors/sound_object_person_following/scripts/sound_object_person_following_node.py @@ -2,14 +2,16 @@ from abc import ABC, abstractmethod import math -import threading import numpy as np from scipy.optimize import dual_annealing -import rospy -from odas_ros.msg import OdasSstArrayStamped -from video_analyzer.msg import VideoAnalysis +import rclpy +import rclpy.node +import rclpy.executors + +from odas_ros_msgs.msg import OdasSstArrayStamped +from perception_msgs.msg import VideoAnalysis from t_top import MovementCommands, vector_to_angles, HEAD_POSE_PITCH_INDEX, HEAD_ZERO_Z @@ -43,27 +45,27 @@ def target(self): class SoundFollower(Follower): - def __init__(self, movement_commands): + def __init__(self, node, movement_commands): + self._node = node self._movement_commands = movement_commands - self._min_sst_activity = rospy.get_param('~min_sst_activity') - self._min_valid_sst_pitch = rospy.get_param('~min_valid_sst_pitch') - self._max_valid_sst_pitch = rospy.get_param('~max_valid_sst_pitch') - self._direction_frame_id = rospy.get_param('~direction_frame_id') + self._min_sst_activity = self._node.declare_parameter('min_sst_activity', 0.1).get_parameter_value().double_value + self._min_valid_sst_pitch = self._node.declare_parameter('min_valid_sst_pitch', -1.4).get_parameter_value().double_value + self._max_valid_sst_pitch = self._node.declare_parameter('max_valid_sst_pitch', 1.4).get_parameter_value().double_value + self._direction_frame_id = self._node.declare_parameter('direction_frame_id', 'odas').get_parameter_value().string_value - self._target_lock = threading.Lock() self._target = None - self._sst_sub = rospy.Subscriber('sst', OdasSstArrayStamped, self._sst_cb, queue_size=1) + self._sst_sub = self._node.create_subscription(OdasSstArrayStamped, 'sst', self._sst_cb, 1) def _sst_cb(self, sst): if self._movement_commands.is_filtering_all_messages: return if len(sst.sources) > 1: - rospy.logerr(f'Invalid sst (len(sst.sources)={len(sst.sources)})') + self._node.get_logger().error(f'Invalid sst (len(sst.sources)={len(sst.sources)})') return if sst.header.frame_id != self._direction_frame_id: - rospy.logerr(f'Invalid direction frame id ({sst.header.frame_id} != {self._direction_frame_id})') + self._node.get_logger().error(f'Invalid direction frame id ({sst.header.frame_id} != {self._direction_frame_id})') return if len(sst.sources) == 0 or sst.sources[0].activity < self._min_sst_activity: return @@ -72,29 +74,27 @@ def _sst_cb(self, sst): if pitch < self._min_valid_sst_pitch or pitch > self._max_valid_sst_pitch: return - with self._target_lock: - self._target = Target.from_sound_following(yaw) + self._target = Target.from_sound_following(yaw) @property def target(self): - with self._target_lock: - return self._target + return self._target class ObjectPersonFollower(Follower): - def __init__(self, camera_3d_calibration, movement_commands): + def __init__(self, node, camera_3d_calibration, movement_commands): + self._node = node self._camera_3d_calibration = camera_3d_calibration self._movement_commands = movement_commands - self._object_classes = set(rospy.get_param('~object_classes')) - self._padding = rospy.get_param('~padding') - self._target_lambda = rospy.get_param('~target_lambda') + self._object_classes = set(self._node.declare_parameter('object_classes', ['all']).get_parameter_value().string_array_value) + self._padding = self._node.declare_parameter('padding', 0.075).get_parameter_value().double_value + self._target_lambda = self._node.declare_parameter('target_lambda', 0.005).get_parameter_value().double_value _verify_padding(self._camera_3d_calibration, self._padding) - self._target_lock = threading.Lock() self._target = None - self._video_analysis_sub = rospy.Subscriber('video_analysis', VideoAnalysis, self._video_analysis_cb, queue_size=1) + self._video_analysis_sub = self._node.create_subscription(VideoAnalysis, 'video_analysis', self._video_analysis_cb, 1) def _video_analysis_cb(self, msg): if self._movement_commands.is_filtering_all_messages: @@ -106,8 +106,7 @@ def _video_analysis_cb(self, msg): else: target = self._find_target(msg, person) - with self._target_lock: - self._target = target + self._target = target def _find_biggest_person(self, objects): person_area_pairs = [(o, o.width_2d * o.height_2d) for o in objects if o.object_class == PERSON_CLASS] @@ -141,8 +140,7 @@ def _find_target_range(self, person): @property def target(self): - with self._target_lock: - return self._target + return self._target def _verify_padding(camera_3d_calibration, padding): @@ -205,7 +203,7 @@ def _get_object_bounding_boxes(self, objects): class SemanticSegmentationObjectPersonFollower(ObjectPersonFollower): def _find_target(self, msg, person, eps=1e-6): if len(msg.semantic_segmentation) == 0: - rospy.logerr('The video analysis must have semantic segmentation.') + self._node.get_logger().error('The video analysis must have semantic segmentation.') return min_x, max_x, min_y, max_y = self._find_target_range(person) @@ -246,39 +244,46 @@ def _get_mask_from_semantic_segmentation(self, semantic_segmentation): return np.isin(class_indexes, desired_class_indexes) -class SoundObjectPersonFollowingNode: +class SoundObjectPersonFollowingNode(rclpy.node.Node): def __init__(self): - self._simulation = rospy.get_param('~simulation') - self._rate = rospy.Rate(rospy.get_param('~control_frequency')) - self._torso_control_alpha = rospy.get_param('~torso_control_alpha') - self._torso_control_p_gain = rospy.get_param('~torso_control_p_gain') - self._head_control_p_gain = rospy.get_param('~head_control_p_gain') - self._min_head_pitch = rospy.get_param('~min_head_pitch_rad') - self._max_head_pitch = rospy.get_param('~max_head_pitch_rad') - self._object_person_follower_type = rospy.get_param('~object_person_follower_type') + super().__init__('sound_object_person_following_node') + + self._simulation = self.declare_parameter('simulation', False).get_parameter_value().bool_value + self._control_frequency = self.declare_parameter('control_frequency', 30.0).get_parameter_value().double_value + self._torso_control_alpha = self.declare_parameter('torso_control_alpha', 0.2).get_parameter_value().double_value + self._torso_control_p_gain = self.declare_parameter('torso_control_p_gain', 0.45).get_parameter_value().double_value + self._head_control_p_gain = self.declare_parameter('head_control_p_gain', 0.45).get_parameter_value().double_value + self._min_head_pitch = self.declare_parameter('min_head_pitch_rad', -0.35).get_parameter_value().double_value + self._max_head_pitch = self.declare_parameter('max_head_pitch_rad', 0.35).get_parameter_value().double_value + self._object_person_follower_type = self.declare_parameter('object_person_follower_type', 'bounding_box').get_parameter_value().string_value self._camera_3d_calibration = Camera3dCalibration.load_json_file() - self._movement_commands = MovementCommands(self._simulation, namespace='sound_object_person_following') - self._sound_follower = SoundFollower(self._movement_commands) + self._movement_commands = MovementCommands(self, self._simulation, namespace='sound_object_person_following') + self._sound_follower = SoundFollower(self, self._movement_commands) if self._object_person_follower_type == 'bounding_box': - self._object_person_follower = BoundingBoxObjectPersonFollower(self._camera_3d_calibration, self._movement_commands) + self._object_person_follower = BoundingBoxObjectPersonFollower(self, self._camera_3d_calibration, self._movement_commands) elif self._object_person_follower_type == 'semantic_segmentation': - self._object_person_follower = SemanticSegmentationObjectPersonFollower(self._camera_3d_calibration, self._movement_commands) + self._object_person_follower = SemanticSegmentationObjectPersonFollower(self, self._camera_3d_calibration, self._movement_commands) else: - raise ValueError(f'Invalid object_person_follower_type (object_person_follower_type={object_person_follower_type})') + raise ValueError(f'Invalid object_person_follower_type (object_person_follower_type={self._object_person_follower_type})') - def run(self): - while not rospy.is_shutdown(): - self._rate.sleep() - if self._movement_commands.is_filtering_all_messages: - continue + self._timer = self.create_timer(1 / self._control_frequency, self._timer_callback) + + def _timer_callback(self): + if self._movement_commands.is_filtering_all_messages: + return + + target = self._object_person_follower.target + if target is None: + target = self._sound_follower.target - target = self._object_person_follower.target - if target is None: - target = self._sound_follower.target + if target is not None: + self._update_from_target(target) - if target is not None: - self._update_from_target(target) + def run(self): + executor = rclpy.executors.MultiThreadedExecutor(num_threads=2) + executor.add_node(self) + executor.spin() def _update_from_target(self, target): if target.yaw is not None: @@ -312,13 +317,18 @@ def _update_head_from_image_y(self, current_image_y): def main(): - rospy.init_node('sound_object_person_following_node') - explore_node = SoundObjectPersonFollowingNode() - explore_node.run() - + rclpy.init() + sound_object_person_following_node = SoundObjectPersonFollowingNode() -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + sound_object_person_following_node.run() + except KeyboardInterrupt: pass + finally: + sound_object_person_following_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/behaviors/sound_object_person_following/setup.py b/ros/behaviors/sound_object_person_following/setup.py deleted file mode 100644 index 41aff439..00000000 --- a/ros/behaviors/sound_object_person_following/setup.py +++ /dev/null @@ -1,12 +0,0 @@ -## ! DO NOT MANUALLY INVOKE THIS setup.py, USE CATKIN INSTEAD - -from setuptools import setup -from catkin_pkg.python_setup import generate_distutils_setup - -# fetch values from package.xml -setup_args = generate_distutils_setup( - packages=['sound_object_person_following'], - package_dir={'': 'src'}, -) - -setup(**setup_args) diff --git a/ros/behaviors/sound_object_person_following/src/sound_object_person_following/__init__.py b/ros/behaviors/sound_object_person_following/sound_object_person_following/__init__.py similarity index 81% rename from ros/behaviors/sound_object_person_following/src/sound_object_person_following/__init__.py rename to ros/behaviors/sound_object_person_following/sound_object_person_following/__init__.py index b2878844..cad79278 100644 --- a/ros/behaviors/sound_object_person_following/src/sound_object_person_following/__init__.py +++ b/ros/behaviors/sound_object_person_following/sound_object_person_following/__init__.py @@ -1,11 +1,7 @@ import os import json -import rospkg - - -PACKAGE_PATH = rospkg.RosPack().get_path('sound_object_person_following') -CAMERA_3D_CALIBRATION_FILE_PATH = os.path.join(PACKAGE_PATH, 'camera_3d_calibration.json') +CAMERA_3D_CALIBRATION_FILE_PATH = os.path.join(os.environ['HOME'], '.ros', 't-top', 'sound_object_person_following', 'camera_3d_calibration.json') class Camera3dCalibration: @@ -27,6 +23,7 @@ def load_json_file(): return Camera3dCalibration(data['center_x'], data['center_y'], data['width'], data['height']) def save_json_file(self): + os.makedirs(os.path.dirname(CAMERA_3D_CALIBRATION_FILE_PATH), exist_ok=True) with open(CAMERA_3D_CALIBRATION_FILE_PATH, 'w') as file: data = { 'center_x': self.center_x, diff --git a/ros/behaviors/sound_player/CMakeLists.txt b/ros/behaviors/sound_player/CMakeLists.txt index 95e1fb4a..4154d67d 100644 --- a/ros/behaviors/sound_player/CMakeLists.txt +++ b/ros/behaviors/sound_player/CMakeLists.txt @@ -1,205 +1,31 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(sound_player) -## Compile as C++11, supported in ROS Kinetic and newer -# add_compile_options(-std=c++11) - -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - audio_utils - message_generation - rospy - hbba_lite - ) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -add_message_files( - FILES - SoundFile.msg - Started.msg - Done.msg +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(audio_utils_msgs REQUIRED) +find_package(hbba_lite REQUIRED) +find_package(behavior_msgs REQUIRED) +find_package(time_utils REQUIRED) + +# Python Nodes +install(PROGRAMS + scripts/sound_player_node.py + DESTINATION lib/${PROJECT_NAME} ) -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -generate_messages() - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( - # INCLUDE_DIRS include - # LIBRARIES sound_player - # CATKIN_DEPENDS audio_utils message_generation rospy - # DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( - # include - ${catkin_INCLUDE_DIRS} -) - -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/sound_player.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -# add_executable(${PROJECT_NAME}_node src/sound_player_node.cpp) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -# target_link_libraries(${PROJECT_NAME}_node -# ${catkin_LIBRARIES} -# ) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -# catkin_install_python(PROGRAMS -# scripts/my_python_script -# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_sound_player.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() - -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/behaviors/sound_player/README.md b/ros/behaviors/sound_player/README.md index b336d21a..de776c82 100644 --- a/ros/behaviors/sound_player/README.md +++ b/ros/behaviors/sound_player/README.md @@ -10,20 +10,20 @@ This node plays sound files. #### Parameters -- `sampling_frequency` (int): The output sampling frequency. -- `frame_sample_count` (double): The number of sample in each audio frame. +- `sampling_frequency` (int): The output sampling frequency. The default value is 16000. +- `frame_sample_count` (double): The number of sample in each audio frame. The default value is 1024. #### Subscribed Topics -- `sound_player/file` ([sound_player/SoundFile](msg/SoundFile.msg)): The sound file to play. +- `sound_player/file` ([behavior_msgs/SoundFile](../behavior_msgs/msg/SoundFile.msg)): The sound file to play. #### Published Topics -- `audio_out` ([audio_utils/AudioFrame](https://github.com/introlab/audio_utils/blob/main/msg/AudioFrame.msg)): The +- `audio_out` ([audio_utils_msgs/AudioFrame](https://github.com/introlab/audio_utils/blob/ros2/audio_utils_msgs/msg/AudioFrame.msg)): The sound (mono, float format). -- `sound_player/done` ([sound_player/Done](msg/Done.msg)): Indicates that the speech is finished. +- `sound_player/done` ([behavior_msgs/Done](../behavior_msgs/msg/Done.msg)): Indicates that the speech is finished. #### Services -- `audio_out/filter_state` ([hbba_lite/SetOnOffFilterState](../../hbba_lite/srv/SetOnOffFilterState.srv)): The HBBA +- `audio_out/filter_state` ([hbba_lite_srvs/SetOnOffFilterState](../../utils/hbba_lite/hbba_lite_srvs/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the behavior. diff --git a/ros/behaviors/sound_player/msg/Done.msg b/ros/behaviors/sound_player/msg/Done.msg deleted file mode 100644 index dae3f6dd..00000000 --- a/ros/behaviors/sound_player/msg/Done.msg +++ /dev/null @@ -1,2 +0,0 @@ -uint64 id -bool ok diff --git a/ros/behaviors/sound_player/package.xml b/ros/behaviors/sound_player/package.xml index c223ce79..238a50bc 100644 --- a/ros/behaviors/sound_player/package.xml +++ b/ros/behaviors/sound_player/package.xml @@ -1,69 +1,28 @@ - + + sound_player 0.0.0 The sound_player package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rclpy + audio_utils_msgs + hbba_lite + behavior_msgs + time_utils - - - - TODO + rosidl_default_runtime + ros2launch + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - audio_utils - message_generation - rospy - hbba_lite - audio_utils - rospy - hbba_lite - audio_utils - rospy - hbba_lite - - - - - + ament_cmake diff --git a/ros/behaviors/sound_player/scripts/sound_player_node.py b/ros/behaviors/sound_player/scripts/sound_player_node.py index 61b006ee..b61ba1b4 100755 --- a/ros/behaviors/sound_player/scripts/sound_player_node.py +++ b/ros/behaviors/sound_player/scripts/sound_player_node.py @@ -1,48 +1,52 @@ #!/usr/bin/env python3 -import threading +import time from pathlib import Path import numpy as np import librosa -import rospy -from sound_player.msg import SoundFile, Started, Done -from audio_utils.msg import AudioFrame +import rclpy +import rclpy.node + +from behavior_msgs.msg import SoundFile, SoundStarted, Done +from audio_utils_msgs.msg import AudioFrame import hbba_lite +import time_utils -class SoundPlayerNode: +class SoundPlayerNode(rclpy.node.Node): def __init__(self): - self._sampling_frequency = rospy.get_param('~sampling_frequency') - self._frame_sample_count = rospy.get_param('~frame_sample_count') + super().__init__('sound_player_node') + + self._sampling_frequency = self.declare_parameter('sampling_frequency', 16000).get_parameter_value().integer_value + self._frame_sample_count = self.declare_parameter('frame_sample_count', 1024).get_parameter_value().integer_value - self._audio_pub = hbba_lite.OnOffHbbaPublisher('audio_out', AudioFrame, queue_size=5) - self._started_pub = rospy.Publisher('sound_player/started', Started, queue_size=5) - self._done_pub = rospy.Publisher('sound_player/done', Done, queue_size=5) + self._audio_pub = hbba_lite.OnOffHbbaPublisher(self, AudioFrame, 'audio_out', 5) + self._started_pub = self.create_publisher(SoundStarted, 'sound_player/started', 5) + self._done_pub = self.create_publisher(Done, 'sound_player/done', 5) - self._file_sub_lock = threading.Lock() - self._file_sub = rospy.Subscriber('sound_player/file', SoundFile, self._on_file_received_cb, queue_size=1) + self._file_sub = self.create_subscription(SoundFile, 'sound_player/file', self._on_file_received_cb, 1) def _on_file_received_cb(self, msg): - with self._file_sub_lock: - if self._audio_pub.is_filtering_all_messages: - return + if self._audio_pub.is_filtering_all_messages: + return - try: - self._play_audio(msg.id, msg.path) - ok = True - except Exception as e: - rospy.logerr(f'Unable to play the sound ({e})') - ok = False - self._done_pub.publish(Done(id=msg.id, ok=ok)) + try: + self._play_audio(msg.id, msg.path) + ok = True + except Exception as e: + self.get_logger().error(f'Unable to play the sound ({e})') + ok = False + + self._done_pub.publish(Done(id=msg.id, ok=ok)) def _play_audio(self, id, path): frames = self._load_frames(Path(path).expanduser().resolve()) - self._started_pub.publish(Started(id=id)) + self._started_pub.publish(SoundStarted(id=id)) audio_frame = AudioFrame() audio_frame.format = 'float' @@ -50,12 +54,12 @@ def _play_audio(self, id, path): audio_frame.sampling_frequency = self._sampling_frequency audio_frame.frame_sample_count = self._frame_sample_count - rate = rospy.Rate(self._sampling_frequency / self._frame_sample_count) + rate = time_utils.Rate(self._sampling_frequency / self._frame_sample_count) for frame in frames: if self._audio_pub.is_filtering_all_messages: break - audio_frame.header.stamp = rospy.Time.now() + audio_frame.header.stamp = self.get_clock().now().to_msg() audio_frame.data = frame.tobytes() self._audio_pub.publish(audio_frame) @@ -63,23 +67,29 @@ def _play_audio(self, id, path): def _load_frames(self, file_path): waveform, _ = librosa.load(file_path, sr=self._sampling_frequency, res_type='kaiser_fast') + waveform = librosa.to_mono(waveform) pad = (self._frame_sample_count - (waveform.shape[0] % self._frame_sample_count)) % self._frame_sample_count waveform.resize(waveform.shape[0] + pad, refcheck=False) frames = np.split(waveform, np.arange(self._frame_sample_count, len(waveform), self._frame_sample_count)) return frames def run(self): - rospy.spin() + rclpy.spin(self) def main(): - rospy.init_node('sound_player_node') + rclpy.init() sound_player_node = SoundPlayerNode() - sound_player_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + sound_player_node.run() + except KeyboardInterrupt: pass + finally: + sound_player_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/behaviors/talk/.gitignore b/ros/behaviors/talk/.gitignore deleted file mode 100644 index 57293dd7..00000000 --- a/ros/behaviors/talk/.gitignore +++ /dev/null @@ -1 +0,0 @@ -audio_files/ diff --git a/ros/behaviors/talk/CMakeLists.txt b/ros/behaviors/talk/CMakeLists.txt index e4dfaee0..7c0730c1 100644 --- a/ros/behaviors/talk/CMakeLists.txt +++ b/ros/behaviors/talk/CMakeLists.txt @@ -1,211 +1,35 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(talk) -## Compile as C++11, supported in ROS Kinetic and newer -# add_compile_options(-std=c++11) - -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - roscpp - rospy - std_msgs - message_generation - audio_utils - hbba_lite - piper_ros - ) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -add_message_files( - FILES - Text.msg - Done.msg - Statistics.msg -) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -generate_messages( - DEPENDENCIES - std_msgs -) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( - # INCLUDE_DIRS include - # LIBRARIES talk - CATKIN_DEPENDS roscpp rospy std_msgs - # DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( - # include - ${catkin_INCLUDE_DIRS} +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(audio_utils_msgs REQUIRED) +find_package(hbba_lite REQUIRED) +find_package(behavior_srvs REQUIRED) +find_package(behavior_msgs REQUIRED) +find_package(time_utils REQUIRED) + +# Python Librairies +ament_python_install_package(${PROJECT_NAME}) + +# Python Nodes +install(PROGRAMS + scripts/talk_node.py + DESTINATION lib/${PROJECT_NAME} ) -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/talk.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -# add_executable(${PROJECT_NAME}_node src/talk_node.cpp) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -# target_link_libraries(${PROJECT_NAME}_node -# ${catkin_LIBRARIES} -# ) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -catkin_install_python(PROGRAMS - scripts/talk_node.py - DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} - ) - -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_talk.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() - -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/behaviors/talk/README.md b/ros/behaviors/talk/README.md index 29cf5e3c..c0f51275 100644 --- a/ros/behaviors/talk/README.md +++ b/ros/behaviors/talk/README.md @@ -10,28 +10,28 @@ This node makes T-Top talk and move its lips accordingly. It uses Google Cloud T #### Parameters -- `language` (string): The language (en or fr). -- `gender` (string): The gender (female or male). -- `speaking_rate` (doule): The speaking rate (range: [0.25, 4.0]). -- `generator_type` (string): The generator type (google or piper). The Google generator uses the cloud and the Piper generator does not. -- `mouth_signal_gain` (double): The gain to apply after the filter calculating the mouth signal. -- `sampling_frequency` (int): The output sampling frequency. -- `frame_sample_count` (double): The number of sample in each audio frame. -- `done_delay_s` (double): The delay before sending the talk done message (default: 0.5). +- `language` (string): The language (en or fr). The default value is en. +- `gender` (string): The gender (female or male). The default value is male. +- `speaking_rate` (doule): The speaking rate (range: [0.25, 4.0]). The default value is 1.0. +- `generator_type` (string): The generator type (google or piper). The Google generator uses the cloud and the Piper generator does not. The default value is piper. +- `mouth_signal_gain` (double): The gain to apply after the filter calculating the mouth signal. The default value is 0.04. +- `sampling_frequency` (int): The output sampling frequency. The default value is 16000. +- `frame_sample_count` (double): The number of sample in each audio frame. The default value is 1024. +- `done_delay_s` (double): The delay before sending the talk done message. The default value is 0.5. #### Subscribed Topics -- `talk/text` ([talk/Text](msg/Text.msg)): The text to be said. +- `talk/text` ([behavior_msgs/Text](../behavior_msgs/msg/Text.msg)): The text to be said. #### Published Topics -- `face/mouth_signal_scale` ([std_msgs/Float32](http://docs.ros.org/en/noetic/api/std_msgs/html/msg/Float32.html)): +- `face/mouth_signal_scale` ([std_msgs/Float32](https://docs.ros.org/en/humble/p/std_msgs/interfaces/msg/Float32.html)): Indicates how much the mouth must be open. -- `audio_out` ([audio_utils/AudioFrame](https://github.com/introlab/audio_utils/blob/main/msg/AudioFrame.msg)): The +- `audio_out` ([audio_utils_msgs/AudioFrame](https://github.com/introlab/audio_utils/blob/ros2/audio_utils_msgs/msg/AudioFrame.msg)): The speech sound (mono, float format). -- `talk/done` ([talk/Done](msg/Done.msg)): Indicates that the speech is finished. +- `talk/done` ([behavior_msgs/Done](../behavior_msgs/msg/Done.msg)): Indicates that the speech is finished. #### Services -- `audio_out/filter_state` ([hbba_lite/SetOnOffFilterState](../../hbba_lite/srv/SetOnOffFilterState.srv)): The HBBA +- `audio_out/filter_state` ([hbba_lite_srvs/SetOnOffFilterState](../../utils/hbba_lite/hbba_lite_srvs/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the behavior. diff --git a/ros/behaviors/talk/msg/Done.msg b/ros/behaviors/talk/msg/Done.msg deleted file mode 100644 index dae3f6dd..00000000 --- a/ros/behaviors/talk/msg/Done.msg +++ /dev/null @@ -1,2 +0,0 @@ -uint64 id -bool ok diff --git a/ros/behaviors/talk/package.xml b/ros/behaviors/talk/package.xml index a18c5100..461c6713 100644 --- a/ros/behaviors/talk/package.xml +++ b/ros/behaviors/talk/package.xml @@ -1,80 +1,30 @@ - + + talk 0.0.0 The talk package + Marc-Antoine Maheux + GPL-3.0 license - - - - alexandre + ament_cmake + rclpy + std_msgs + audio_utils_msgs + hbba_lite + behavior_srvs + behavior_msgs + time_utils - - - - TODO + rosidl_default_runtime + ros2launch + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - roscpp - rospy - std_msgs - audio_utils - hbba_lite - message_generation - piper_ros - roscpp - rospy - std_msgs - audio_utils - hbba_lite - message_generation - piper_ros - roscpp - rospy - std_msgs - audio_utils - hbba_lite - message_generation - piper_ros - - - - - + ament_cmake diff --git a/ros/behaviors/talk/scripts/talk_node.py b/ros/behaviors/talk/scripts/talk_node.py index b6444590..b734b906 100755 --- a/ros/behaviors/talk/scripts/talk_node.py +++ b/ros/behaviors/talk/scripts/talk_node.py @@ -2,7 +2,7 @@ # -*- encoding: utf-8 -*- import os -import threading +import time from datetime import datetime import numpy as np @@ -10,83 +10,84 @@ import librosa -import rospy -import rospkg +import rclpy +import rclpy.node +import rclpy.executors + from std_msgs.msg import Float32 -from talk.msg import Text, Done, Statistics -from audio_utils.msg import AudioFrame +from behavior_msgs.msg import Text, Done, Statistics +from audio_utils_msgs.msg import AudioFrame import hbba_lite +import time_utils from talk.lib_voice_generator import Language, Gender from talk.lib_voice_generator import GoogleVoiceGenerator, PiperVoiceGenerator, CachedVoiceGenerator -class TalkNode: +class TalkNode(rclpy.node.Node): def __init__(self): - language = Language.from_name(rospy.get_param('~language')) - gender = Gender.from_name(rospy.get_param('~gender')) - speaking_rate = rospy.get_param('~speaking_rate') - generator_type = rospy.get_param('~generator_type') - cache_size = rospy.get_param('~cache_size') + super().__init__('talk_node') + + language = Language.from_name(self.declare_parameter('language', 'en').get_parameter_value().string_value) + gender = Gender.from_name(self.declare_parameter('gender', 'male').get_parameter_value().string_value) + speaking_rate = self.declare_parameter('speaking_rate', 1.0).get_parameter_value().double_value + generator_type = self.declare_parameter('generator_type', 'piper').get_parameter_value().string_value + cache_size = self.declare_parameter('cache_size', 2000).get_parameter_value().integer_value - self._mouth_signal_gain = rospy.get_param('~mouth_signal_gain') - self._sampling_frequency = rospy.get_param('~sampling_frequency') - self._frame_sample_count = rospy.get_param('~frame_sample_count') - self._done_delay_s = rospy.get_param('~done_delay_s', 0.5) + self._mouth_signal_gain = self.declare_parameter('mouth_signal_gain', 0.04).get_parameter_value().double_value + self._sampling_frequency = self.declare_parameter('sampling_frequency', 16000).get_parameter_value().integer_value + self._frame_sample_count = self.declare_parameter('frame_sample_count', 1024).get_parameter_value().integer_value + self._done_delay_s = self.declare_parameter('done_delay_s', 0.5).get_parameter_value().double_value - self._rospack = rospkg.RosPack() - self._pkg_path = self._rospack.get_path('talk') - audio_directory_path = os.path.join(self._pkg_path, 'audio_files') + audio_directory_path = os.path.join(os.environ['HOME'], '.ros', 't-top', 'talk', 'audio_files') if generator_type == 'google': self._voice_generator = GoogleVoiceGenerator(audio_directory_path, language, gender, speaking_rate) elif generator_type == 'piper': - self._voice_generator = PiperVoiceGenerator(audio_directory_path, language, gender, speaking_rate) + self._voice_generator = PiperVoiceGenerator(self, audio_directory_path, language, gender, speaking_rate) else: raise ValueError(f'Invalid generator type ({generator_type})') if cache_size > 0: self._voice_generator = CachedVoiceGenerator(self._voice_generator, cache_size) - self._mouth_signal_scale_pub = rospy.Publisher('face/mouth_signal_scale', Float32, queue_size=5) - self._audio_pub = hbba_lite.OnOffHbbaPublisher('audio_out', AudioFrame, queue_size=5) - self._done_talking_pub = rospy.Publisher('talk/done', Done, queue_size=5) - self._stats_pub = rospy.Publisher('talk/statistics', Statistics, queue_size=5) + self._mouth_signal_scale_pub = self.create_publisher(Float32, 'face/mouth_signal_scale', 5) + self._audio_pub = hbba_lite.OnOffHbbaPublisher(self, AudioFrame, 'audio_out', 5) + self._done_talking_pub = self.create_publisher(Done, 'talk/done', 5) + self._stats_pub = self.create_publisher(Statistics, 'talk/statistics', 5) - self._text_sub_lock = threading.Lock() - self._text_sub = rospy.Subscriber('talk/text', Text, self._on_text_received_cb, queue_size=1) + self._text_sub = self.create_subscription(Text, 'talk/text', self._on_text_received_cb, 1) def _on_text_received_cb(self, msg): - with self._text_sub_lock: - if self._audio_pub.is_filtering_all_messages: - return + if self._audio_pub.is_filtering_all_messages: + return - try: - if msg.text != '': - start_time = datetime.now() - file_path = self._voice_generator.generate(msg.text) - frames = self._load_frames(file_path) - processing_time_s = (datetime.now() - start_time).total_seconds() + try: + if msg.text != '': + start_time = datetime.now() + file_path = self._voice_generator.generate(msg.text) + frames = self._load_frames(file_path) + processing_time_s = (datetime.now() - start_time).total_seconds() - self._publish_stats(msg.text, frames, processing_time_s) + self._publish_stats(msg.text, frames, processing_time_s) - self._play_audio(frames) - self._voice_generator.delete_generated_file(file_path) - rospy.sleep(self._done_delay_s) + self._play_audio(frames) + self._voice_generator.delete_generated_file(file_path) + time.sleep(self._done_delay_s) - ok = True - except Exception as e: - rospy.logerr(f'Unable to talk ({e})') - ok = False + ok = True + except Exception as e: + self.get_logger().error(f'Unable to talk ({e})') + ok = False - self._done_talking_pub.publish(Done(id=msg.id, ok=ok)) + self._done_talking_pub.publish(Done(id=msg.id, ok=ok)) def _publish_stats(self, text, frames, processing_time_s): stats = Statistics() stats.text = text stats.processing_time_s = processing_time_s - stats.header.stamp = rospy.Time.now() + stats.header.stamp = self.get_clock().now().to_msg() stats.total_samples_count = 0 for frame in frames: @@ -106,7 +107,7 @@ def _play_audio(self, frames): audio_frame.sampling_frequency = self._sampling_frequency audio_frame.frame_sample_count = self._frame_sample_count - rate = rospy.Rate(self._sampling_frequency / self._frame_sample_count) + rate = time_utils.Rate(self._sampling_frequency / self._frame_sample_count) for frame in frames: if self._audio_pub.is_filtering_all_messages: break @@ -124,9 +125,10 @@ def _play_audio(self, frames): mouth_signal_msg.data = max(0.0, min(mouth_signal[0] * self._mouth_signal_gain, 1.0)) self._mouth_signal_scale_pub.publish(mouth_signal_msg) - audio_frame.header.stamp = rospy.Time.now() + audio_frame.header.stamp = self.get_clock().now().to_msg() audio_frame.data = frame.tobytes() self._audio_pub.publish(audio_frame) + rate.sleep() mouth_signal_msg.data = 0.0 @@ -134,6 +136,7 @@ def _play_audio(self, frames): def _load_frames(self, file_path): waveform, _ = librosa.load(file_path, sr=self._sampling_frequency, res_type='kaiser_fast') + waveform = librosa.to_mono(waveform) pad = (self._frame_sample_count - (waveform.shape[0] % self._frame_sample_count)) % self._frame_sample_count waveform = np.pad(waveform, (0, pad), 'constant', constant_values=0) frames = np.split(waveform, np.arange(self._frame_sample_count, len(waveform), self._frame_sample_count)) @@ -156,17 +159,28 @@ def _initialize_mouth_signal_filter(self): return mouth_signal_filter_sos, mouth_signal_filter_zi def run(self): - rospy.spin() + executer_thread_count = self._voice_generator.executer_thread_count + if executer_thread_count == 1: + rclpy.spin(self) + else: + executor = rclpy.executors.MultiThreadedExecutor(num_threads=executer_thread_count) + executor.add_node(self) + executor.spin() def main(): - rospy.init_node('talk_node') + rclpy.init() talk_node = TalkNode() - talk_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + talk_node.run() + except KeyboardInterrupt: pass + finally: + talk_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/behaviors/talk/setup.py b/ros/behaviors/talk/setup.py deleted file mode 100644 index 01b86310..00000000 --- a/ros/behaviors/talk/setup.py +++ /dev/null @@ -1,12 +0,0 @@ -## ! DO NOT MANUALLY INVOKE THIS setup.py, USE CATKIN INSTEAD - -from setuptools import setup -from catkin_pkg.python_setup import generate_distutils_setup - -# fetch values from package.xml -setup_args = generate_distutils_setup( - packages=['talk'], - package_dir={'': 'src'}, -) - -setup(**setup_args) diff --git a/ros/perceptions/video_analyzer/src/video_analyzer/__init__.py b/ros/behaviors/talk/talk/__init__.py similarity index 100% rename from ros/perceptions/video_analyzer/src/video_analyzer/__init__.py rename to ros/behaviors/talk/talk/__init__.py diff --git a/ros/behaviors/talk/src/talk/lib_voice_generator.py b/ros/behaviors/talk/talk/lib_voice_generator.py similarity index 86% rename from ros/behaviors/talk/src/talk/lib_voice_generator.py rename to ros/behaviors/talk/talk/lib_voice_generator.py index 27962381..1cb542bd 100644 --- a/ros/behaviors/talk/src/talk/lib_voice_generator.py +++ b/ros/behaviors/talk/talk/lib_voice_generator.py @@ -5,11 +5,15 @@ import json import random from enum import Enum +import asyncio from google.cloud import texttospeech -import rospy -from piper_ros.srv import GenerateSpeechFromText, GenerateSpeechFromTextRequest +import rclpy +import rclpy.node +from rclpy.callback_groups import MutuallyExclusiveCallbackGroup + +from behavior_srvs.srv import GenerateSpeechFromText class Language(Enum): @@ -52,6 +56,10 @@ def __init__(self, directory: str, language: Language, gender: Gender, speaking_ @abstractmethod def generate(self, text: str) -> str: pass + + @property + def executer_thread_count(self): + return 1 def delete_generated_file(self, file_path: str): if os.path.exists(file_path): @@ -102,24 +110,33 @@ def generate(self, text: str) -> str: class PiperVoiceGenerator(VoiceGenerator): - def __init__(self, directory: str, language: Language, gender: Gender, speaking_rate: float): + def __init__(self, node: rclpy.node.Node, directory: str, language: Language, gender: Gender, speaking_rate: float): super().__init__(directory, language, gender, speaking_rate) - self._piper_service = rospy.ServiceProxy('piper/generate_speech_from_text', GenerateSpeechFromText) + self._node = node + self._piper_service = node.create_client(GenerateSpeechFromText, 'piper/generate_speech_from_text', + callback_group=MutuallyExclusiveCallbackGroup()) def generate(self, text: str) -> str: - request = GenerateSpeechFromTextRequest() + request = GenerateSpeechFromText.Request() request.language = self._language.value request.gender = self._gender.value request.length_scale = 1.0 / self._speaking_rate request.text = text request.path = self._generate_random_path('.wav') - response = self._piper_service(request) + future = self._piper_service.call_async(request) + async def wait_future(): + return await future + response = asyncio.run(wait_future()) + if not response.ok: raise RuntimeError(response.message) - return request.path + + @property + def executer_thread_count(self): + return 2 class CachedVoiceGenerator(VoiceGenerator): @@ -186,5 +203,9 @@ def _get_cache_key(self, text: str) -> str: return (f'{type(self._voice_generator).__name__}__{self._language.value}__{self._gender.value}__' f'{self._speaking_rate}__{text}') + @property + def executer_thread_count(self): + return self._voice_generator.executer_thread_count + def delete_generated_file(self, file_path: str): pass diff --git a/ros/behaviors/teleoperation/CMakeLists.txt b/ros/behaviors/teleoperation/CMakeLists.txt index 60b4bfdf..0845a600 100644 --- a/ros/behaviors/teleoperation/CMakeLists.txt +++ b/ros/behaviors/teleoperation/CMakeLists.txt @@ -1,205 +1,21 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.8) project(teleoperation) -## Compile as C++11, supported in ROS Kinetic and newer -# add_compile_options(-std=c++11) +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - hbba_lite - rospy - std_msgs - t_top - geometry_msgs - opentera_webrtc_ros_msgs -) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -# add_message_files( -# FILES -# GestureName.msg -# Done.msg -# ) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# DoAction.srv -# ) +find_package(ament_cmake REQUIRED) -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) +find_package(rclpy REQUIRED) +find_package(geometry_msgs REQUIRED) +find_package(opentera_webrtc_ros_msgs REQUIRED) -## Generate added messages and services with any dependencies listed here -# generate_messages() +find_package(t_top REQUIRED) -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( - # INCLUDE_DIRS include - # LIBRARIES gesture - CATKIN_DEPENDS hbba_lite rospy std_msgs t_top opentera_webrtc_ros_msgs - # DEPENDS system_lib +install(PROGRAMS + scripts/teleoperation_node.py + DESTINATION lib/${PROJECT_NAME} ) -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( - # include - ${catkin_INCLUDE_DIRS} -) - -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/gesture.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -# add_executable(${PROJECT_NAME}_node src/gesture_node.cpp) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -# target_link_libraries(${PROJECT_NAME}_node -# ${catkin_LIBRARIES} -# ) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -catkin_install_python(PROGRAMS - scripts/teleoperation_node.py - DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} - ) - -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_gesture.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() - -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/behaviors/teleoperation/README.md b/ros/behaviors/teleoperation/README.md index 1b8c0e29..5a6c43ab 100644 --- a/ros/behaviors/teleoperation/README.md +++ b/ros/behaviors/teleoperation/README.md @@ -15,20 +15,20 @@ This node allows T-Top to be teleoperated using twist commands. #### Subscribed Topics - `daemon/motor_status` ([daemon_ros_client/MotorStatus](../../daemon_ros_client/msg/MotorStatus.msg)): The motor status. -- `teleoperation/cmd_vel` ([geometry_msgs/Twist]): The twist commands. +- `teleoperation/cmd_vel` ([geometry_msgs/Twist](https://docs.ros.org/en/humble/p/geometry_msgs/interfaces/msg/Twist.html)): The twist commands. #### Published Topics -- `teleoperation/set_head_pose` ([geometry_msgs/PoseStamped](http://docs.ros.org/en/noetic/api/geometry_msgs/html/msg/PoseStamped.html)): +- `teleoperation/set_head_pose` ([geometry_msgs/PoseStamped](https://docs.ros.org/en/humble/p/geometry_msgs/interfaces/msg/PoseStamped.html)): The head pose. -- `teleoperation/set_torso_orientation` ([std_msgs/Float32](http://docs.ros.org/en/noetic/api/std_msgs/html/msg/Float32.html)): The +- `teleoperation/set_torso_orientation` ([std_msgs/Float32](https://docs.ros.org/en/humble/p/std_msgs/interfaces/msg/Float32.html)): The torso orientation. #### Services -- `pose/filter_state` ([hbba_lite/SetOnOffFilterState](../../hbba_lite/srv/SetOnOffFilterState.srv)): The HBBA filter +- `pose/filter_state` ([hbba_lite_srvs/SetOnOffFilterState](../../utils/hbba_lite/hbba_lite_srvs/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the behavior. -- `teleop_do_action` ([teleoperation/DoAction])(srv/DoAction.srv)): The name of a specific action to do: +- `teleop_do_action` ([opentera_webrtc_ros_msgs/SetString](https://github.com/introlab/opentera-webrtc-ros/blob/ros2/opentera_webrtc_ros_msgs/srv/SetString.srv)): The name of a specific action to do: - do_yes - do_no - do_maybe diff --git a/ros/behaviors/teleoperation/package.xml b/ros/behaviors/teleoperation/package.xml index b2e8f7e7..d36f4b81 100644 --- a/ros/behaviors/teleoperation/package.xml +++ b/ros/behaviors/teleoperation/package.xml @@ -1,76 +1,25 @@ - + + teleoperation 0.0.0 The teleoperation package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rclpy - - - - TODO + geometry_msgs + opentera_webrtc_ros_msgs + t_top - - - - + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - hbba_lite - rospy - std_msgs - t_top - geometry_msgs - opentera_webrtc_ros_msgs - hbba_lite - rospy - std_msgs - t_top - geometry_msgs - opentera_webrtc_ros_msgs - hbba_lite - rospy - std_msgs - t_top - opentera_webrtc_ros_msgs - - - - - + ament_cmake diff --git a/ros/behaviors/teleoperation/scripts/teleoperation_node.py b/ros/behaviors/teleoperation/scripts/teleoperation_node.py index 813a3995..d4387f8f 100755 --- a/ros/behaviors/teleoperation/scripts/teleoperation_node.py +++ b/ros/behaviors/teleoperation/scripts/teleoperation_node.py @@ -1,11 +1,21 @@ #!/usr/bin/env python3 -import rospy -from geometry_msgs.msg import Twist from contextlib import contextmanager -from t_top import MovementCommands, HEAD_ZERO_Z -from opentera_webrtc_ros_msgs.srv import SetString, SetStringRequest, SetStringResponse +import rclpy +import rclpy.executors +import rclpy.node +from geometry_msgs.msg import Twist +from opentera_webrtc_ros_msgs.srv import SetString +from t_top import HEAD_ZERO_Z, MovementCommands + +MOVE_YES_TIMEOUT = 10 +MOVE_NO_TIMEOUT = 10 +MOVE_MAYBE_TIMEOUT = 10 +MOVE_HEAD_TO_ORIGIN_TIMEOUT = 5 +MOVE_TORSO_TO_ORIGIN_TIMEOUT = 30 +MOVE_THINKING_TIMEOUT = 5 +MOVE_SAD_TIMEOUT = 5 def twist_is_null(twist: Twist) -> bool: @@ -32,23 +42,23 @@ def __init__(self) -> None: self.is_moving = False -class TeleoperationNode: +class TeleoperationNode(rclpy.node.Node): def __init__(self): - self._simulation = rospy.get_param('~simulation', False) + super().__init__('teleoperation_node') + self._simulation = self.declare_parameter('simulation', False).get_parameter_value().bool_value - self._movement_commands = MovementCommands(self._simulation, namespace='teleoperation') + self._movement_commands = MovementCommands(self, self._simulation, namespace='teleoperation') self._state = TeleopState() - self._twist_sub = rospy.Subscriber( - 'teleoperation/cmd_vel', Twist, self._on_twist_cb, queue_size=1) + self._twist_sub = self.create_subscription( + Twist, 'teleoperation/cmd_vel', self._on_twist_cb, 1) - self._timer = rospy.Timer(rospy.Duration( - self._movement_commands.sleep_time), self._on_timer_cb) + self._timer = self.create_timer(self._movement_commands.sleep_time, self._on_timer_cb) - self._origin_serv = rospy.Service( - "teleop_do_action", SetString, self._do_action_cb) + self._origin_serv = self.create_service( + SetString, "teleop_do_action", self._do_action_cb) - def _on_twist_cb(self, msg): + def _on_twist_cb(self, msg: Twist): if self._movement_commands.is_filtering_all_messages: self._state.is_moving = False return @@ -60,7 +70,7 @@ def _on_twist_cb(self, msg): else: self._move(msg) - def _on_timer_cb(self, _): + def _on_timer_cb(self): if self._state.is_moving: self._movement_commands.move_torso_speed( speed_rad_sec_torso=self._state.current_speed.torso_angle, should_sleep=False) @@ -90,7 +100,7 @@ def _move(self, msg: Twist) -> None: self._state.current_speed = TeleopAngles( torso_angle=msg.angular.z/0.15, head_angle=-1.1*msg.linear.x/0.15) - def _do_action_cb(self, req: SetStringRequest) -> SetStringResponse: + def _do_action_cb(self, req: SetString.Request, res: SetString.Response) -> SetString.Response: jump_table = { "goto_origin": self._goto_origin, "do_yes": self._do_yes, @@ -102,13 +112,19 @@ def _do_action_cb(self, req: SetStringRequest) -> SetStringResponse: if req.data in jump_table: if self._movement_commands.is_filtering_all_messages: - return SetStringResponse(success=False, message="HBBA filter is active") + res.success = False + res.message = "HBBA filter is active" + return res jump_table[req.data]() - return SetStringResponse(success=True, message="") + res.success = True + res.message = "" + return res else: - return SetStringResponse(success=False, message=f"'{req.data}' not in {list(jump_table.keys())}") + res.success = False + res.message = f"'{req.data}' not in {list(jump_table.keys())}" + return res @contextmanager def _pause_moving(self): @@ -121,41 +137,46 @@ def _pause_moving(self): def _goto_origin(self) -> None: with self._pause_moving(): - self._movement_commands.move_head_to_origin(False) - self._movement_commands.move_torso_to_origin(False) + self._movement_commands.move_head_to_origin(False, timeout=MOVE_HEAD_TO_ORIGIN_TIMEOUT) + self._movement_commands.move_torso_to_origin(False, timeout=MOVE_TORSO_TO_ORIGIN_TIMEOUT) def _do_yes(self) -> None: with self._pause_moving(): - self._movement_commands.move_yes(count=1) + self._movement_commands.move_yes(count=1, timeout=MOVE_YES_TIMEOUT) def _do_no(self) -> None: with self._pause_moving(): - self._movement_commands.move_no(count=1) + self._movement_commands.move_no(count=1, timeout=MOVE_NO_TIMEOUT) def _do_maybe(self) -> None: with self._pause_moving(): - self._movement_commands.move_maybe(count=1) + self._movement_commands.move_maybe(count=1, timeout=MOVE_MAYBE_TIMEOUT) def _goto_origin_head(self) -> None: with self._pause_moving(): - self._movement_commands.move_head_to_origin(False) + self._movement_commands.move_head_to_origin(False, timeout=MOVE_HEAD_TO_ORIGIN_TIMEOUT) def _goto_origin_torso(self) -> None: with self._pause_moving(): - self._movement_commands.move_torso_to_origin(False) + self._movement_commands.move_torso_to_origin(False, timeout=MOVE_TORSO_TO_ORIGIN_TIMEOUT) def run(self): - rospy.spin() - + executor = rclpy.executors.MultiThreadedExecutor(num_threads=2) + executor.add_node(self) + executor.spin() def main(): - rospy.init_node('teleoperation_node') + rclpy.init() teleop_node = TeleoperationNode() - teleop_node.run() + + try: + teleop_node.run() + except KeyboardInterrupt: + pass + teleop_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() if __name__ == '__main__': - try: - main() - except rospy.ROSInterruptException: - pass + main() diff --git a/ros/behaviors/too_close_reaction/CMakeLists.txt b/ros/behaviors/too_close_reaction/CMakeLists.txt index b0f9313f..51ab2b59 100644 --- a/ros/behaviors/too_close_reaction/CMakeLists.txt +++ b/ros/behaviors/too_close_reaction/CMakeLists.txt @@ -1,208 +1,32 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(too_close_reaction) -## Compile as C++11, supported in ROS Kinetic and newer -# add_compile_options(-std=c++11) - -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - cv_bridge - geometry_msgs - hbba_lite - rospy - sensor_msgs -) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -# add_message_files( -# FILES -# Message1.msg -# Message2.msg -# ) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -# generate_messages( -# DEPENDENCIES -# geometry_msgs# sensor_msgs -# ) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( -# INCLUDE_DIRS include -# LIBRARIES too_close_reaction -# CATKIN_DEPENDS cv_bridge geometry_msgs hbba_lite rospy sensor_msgs -# DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( -# include - ${catkin_INCLUDE_DIRS} -) - -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/too_close_reaction.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -# add_executable(${PROJECT_NAME}_node src/too_close_reaction_node.cpp) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -# target_link_libraries(${PROJECT_NAME}_node -# ${catkin_LIBRARIES} -# ) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -catkin_install_python(PROGRAMS +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclpy REQUIRED) +find_package(cv_bridge REQUIRED) +find_package(geometry_msgs REQUIRED) +find_package(hbba_lite REQUIRED) +find_package(sensor_msgs REQUIRED) + +# Python Nodes +install(PROGRAMS scripts/too_close_reaction_node.py - DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} + DESTINATION lib/${PROJECT_NAME} ) -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_too_close_reaction.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() - -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/behaviors/too_close_reaction/README.md b/ros/behaviors/too_close_reaction/README.md index 76a011dc..3c8b1850 100644 --- a/ros/behaviors/too_close_reaction/README.md +++ b/ros/behaviors/too_close_reaction/README.md @@ -10,21 +10,21 @@ This node makes T-Top move back its head when someone is too close to T-Top. #### Parameters -- `max_offset_m` (double): The maximum distance in meter to move back the head. -- `too_close_start_distance_m` (double): The start distance to move back the head. -- `too_close_end_distance_m` (double): The end distance to move back the head. -- `pixel_ratio` (double): The pixel ratio to measure de distance. +- `max_offset_m` (double): The maximum distance in meter to move back the head. The default value is 0.01. +- `too_close_start_distance_m` (double): The start distance to move back the head. The default value is 0.5. +- `too_close_end_distance_m` (double): The end distance to move back the head. The default value is 0.25. +- `pixel_ratio` (double): The pixel ratio to measure de distance. The default value is 0.01. #### Subscribed Topics -- `depth_image_raw` ([sensor_msgs/Image](http://docs.ros.org/en/noetic/api/sensor_msgs/html/msg/Image.html)): The depth image. +- `depth_image_raw` ([sensor_msgs/Image](https://docs.ros.org/en/humble/p/sensor_msgs/interfaces/msg/Image.html)): The depth image. #### Published Topics -- `too_close_reaction/set_head_pose` ([geometry_msgs/PoseStamped](http://docs.ros.org/en/noetic/api/geometry_msgs/html/msg/PoseStamped.html)): +- `too_close_reaction/set_head_pose` ([geometry_msgs/PoseStamped](https://docs.ros.org/en/humble/p/geometry_msgs/interfaces/msg/PoseStamped.html)): The head pose offset. #### Services -- `depth_image_raw/filter_state` ([hbba_lite/SetOnOffFilterState](../../utils/hbba_lite/srv/SetOnOffFilterState.srv)): The HBBA filter +- `depth_image_raw/filter_state` ([hbba_lite_srvs/SetOnOffFilterState](../../utils/hbba_lite/hbba_lite_srvs/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the behavior. diff --git a/ros/behaviors/too_close_reaction/package.xml b/ros/behaviors/too_close_reaction/package.xml index ff46b2e2..04f9a2f8 100644 --- a/ros/behaviors/too_close_reaction/package.xml +++ b/ros/behaviors/too_close_reaction/package.xml @@ -1,74 +1,28 @@ - + + too_close_reaction 0.0.0 The too_close_reaction package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rclpy + cv_bridge + geometry_msgs + hbba_lite + sensor_msgs - - - - TODO + rosidl_default_runtime + ros2launch + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - cv_bridge - geometry_msgs - hbba_lite - rospy - sensor_msgs - cv_bridge - geometry_msgs - hbba_lite - rospy - sensor_msgs - cv_bridge - geometry_msgs - hbba_lite - rospy - sensor_msgs - - - - - + ament_cmake diff --git a/ros/behaviors/too_close_reaction/scripts/too_close_reaction_node.py b/ros/behaviors/too_close_reaction/scripts/too_close_reaction_node.py index f9f208ff..7586fe10 100755 --- a/ros/behaviors/too_close_reaction/scripts/too_close_reaction_node.py +++ b/ros/behaviors/too_close_reaction/scripts/too_close_reaction_node.py @@ -2,7 +2,9 @@ import numpy as np import cv2 -import rospy +import rclpy +import rclpy.node + from cv_bridge import CvBridge from geometry_msgs.msg import PoseStamped @@ -11,24 +13,26 @@ import hbba_lite -class TooCloseReactionNode: +class TooCloseReactionNode(rclpy.node.Node): def __init__(self): - self._max_offset_m = rospy.get_param('~max_offset_m', 0.01) - self._too_close_start_distance_m = rospy.get_param('~too_close_start_distance_m', 0.5) - self._too_close_end_distance_m = rospy.get_param('~too_close_end_distance_m', 0.25) - self._pixel_ratio = rospy.get_param('~pixel_ratio', 0.01) + super().__init__('too_close_reaction_node') + + self._max_offset_m = self.declare_parameter('max_offset_m', 0.01).get_parameter_value().double_value + self._too_close_start_distance_m = self.declare_parameter('too_close_start_distance_m', 0.5).get_parameter_value().double_value + self._too_close_end_distance_m = self.declare_parameter('too_close_end_distance_m', 0.25).get_parameter_value().double_value + self._pixel_ratio = self.declare_parameter('pixel_ratio', 0.01).get_parameter_value().double_value self._cv_bridge = CvBridge() self._current_offset_m = 0.0 - self._head_pose_pub = rospy.Publisher('too_close_reaction/set_head_pose', PoseStamped, queue_size=1) - self._depth_image_sub = hbba_lite.OnOffHbbaSubscriber('depth_image_raw', Image, self._image_cb, queue_size=1) + self._head_pose_pub = self.create_publisher(PoseStamped, 'too_close_reaction/set_head_pose', 1) + self._depth_image_sub = hbba_lite.OnOffHbbaSubscriber(self, Image, 'depth_image_raw', self._image_cb, 1) self._depth_image_sub.on_filter_state_changed(self._hbba_filter_state_cb) def _image_cb(self, msg): if msg.encoding != '16UC1': - rospy.logerr('Invalid depth image encoding') + self.get_logger().error('Invalid depth image encoding') depth_image = self._cv_bridge.imgmsg_to_cv2(msg, '16UC1') distance_m = self._compute_distance(depth_image) - self._current_offset_m @@ -63,29 +67,34 @@ def _send_pose(self, offset_m): pose_msg = PoseStamped() pose_msg.header.frame_id = 'stewart_base' - pose_msg.pose.position.x = -offset_m - pose_msg.pose.position.y = 0 - pose_msg.pose.position.z = 0 + pose_msg.pose.position.x = float(-offset_m) + pose_msg.pose.position.y = 0.0 + pose_msg.pose.position.z = 0.0 - pose_msg.pose.orientation.x = 0 - pose_msg.pose.orientation.y = 0 - pose_msg.pose.orientation.z = 0 - pose_msg.pose.orientation.w = 1 + pose_msg.pose.orientation.x = 0.0 + pose_msg.pose.orientation.y = 0.0 + pose_msg.pose.orientation.z = 0.0 + pose_msg.pose.orientation.w = 1.0 self._head_pose_pub.publish(pose_msg) def run(self): - rospy.spin() + rclpy.spin(self) def main(): - rospy.init_node('too_close_reaction_node') + rclpy.init() too_close_reaction_node = TooCloseReactionNode() - too_close_reaction_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + too_close_reaction_node.run() + except KeyboardInterrupt: pass + finally: + too_close_reaction_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/daemon_ros_client/CMakeLists.txt b/ros/daemon_ros_client/CMakeLists.txt index 3c997763..404f2dff 100644 --- a/ros/daemon_ros_client/CMakeLists.txt +++ b/ros/daemon_ros_client/CMakeLists.txt @@ -1,148 +1,44 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(daemon_ros_client) -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - geometry_msgs - message_generation - roscpp - sensor_msgs - std_msgs - tf2 - tf2_ros -) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() -################################################ -## Declare ROS messages, services and actions ## -################################################ +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() -## Generate messages in the 'msg' folder -add_message_files( - FILES - BaseStatus.msg - MotorStatus.msg - LedColor.msg - LedColors.msg -) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclcpp REQUIRED) +find_package(std_msgs REQUIRED) +find_package(geometry_msgs REQUIRED) +find_package(sensor_msgs REQUIRED) +find_package(tf2 REQUIRED) +find_package(tf2_ros REQUIRED) +find_package(rosidl_default_generators REQUIRED) -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) -## Generate added messages and services with any dependencies listed here -generate_messages( - DEPENDENCIES - geometry_msgs - sensor_msgs - std_msgs +# Generate messages +rosidl_generate_interfaces(${PROJECT_NAME} + "msg/BaseStatus.msg" + "msg/MotorStatus.msg" + "msg/LedColor.msg" + "msg/LedColors.msg" + DEPENDENCIES std_msgs geometry_msgs sensor_msgs ) -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( -# INCLUDE_DIRS include -# LIBRARIES daemon_ros_client -# CATKIN_DEPENDS geometry_msgs message_generation roscpp sensor_msgs std_msgs -# DEPENDS system_lib -) - -########### -## Build ## -########### - include(../../system/common/common.cmake) -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( -# include - ${catkin_INCLUDE_DIRS} -) - -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/daemon_ros_client.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide +# C++ Nodes set(app_headers src/DaemonRosClientNode.h @@ -156,75 +52,10 @@ set (app_sources qt5_wrap_cpp(app_headers_moc_srcs ${app_headers}) -add_executable(${PROJECT_NAME}_node ${app_headers} ${app_sources} ${app_headers_moc_srcs}) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -target_link_libraries(${PROJECT_NAME}_node - ${catkin_LIBRARIES} - serial_communication_common -) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -# catkin_install_python(PROGRAMS -# scripts/my_python_script -# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_daemon_ros_client.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() +add_executable(daemon_ros_client_node ${app_headers} ${app_sources} ${app_headers_moc_srcs}) +ament_target_dependencies(daemon_ros_client_node rclcpp std_msgs geometry_msgs sensor_msgs tf2 tf2_ros) +target_link_libraries(daemon_ros_client_node serial_communication_common) +rosidl_target_interfaces(daemon_ros_client_node ${PROJECT_NAME} "rosidl_typesupport_cpp") +install(TARGETS daemon_ros_client_node DESTINATION lib/${PROJECT_NAME}) -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/daemon_ros_client/launch/client.launch b/ros/daemon_ros_client/launch/client.launch deleted file mode 100644 index 85a90f28..00000000 --- a/ros/daemon_ros_client/launch/client.launch +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/ros/daemon_ros_client/msg/BaseStatus.msg b/ros/daemon_ros_client/msg/BaseStatus.msg index e94d5e1a..c33c698f 100644 --- a/ros/daemon_ros_client/msg/BaseStatus.msg +++ b/ros/daemon_ros_client/msg/BaseStatus.msg @@ -1,4 +1,4 @@ -Header header +std_msgs/Header header bool is_psu_connected bool has_charger_error bool is_battery_charging diff --git a/ros/daemon_ros_client/msg/MotorStatus.msg b/ros/daemon_ros_client/msg/MotorStatus.msg index b99b436c..2f9df2ad 100644 --- a/ros/daemon_ros_client/msg/MotorStatus.msg +++ b/ros/daemon_ros_client/msg/MotorStatus.msg @@ -1,4 +1,4 @@ -Header header +std_msgs/Header header float32 torso_orientation int16 torso_servo_speed diff --git a/ros/daemon_ros_client/package.xml b/ros/daemon_ros_client/package.xml index 2637506a..bae8edb9 100644 --- a/ros/daemon_ros_client/package.xml +++ b/ros/daemon_ros_client/package.xml @@ -1,78 +1,31 @@ - + + daemon_ros_client 0.0.0 The daemon_ros_client package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rosidl_default_generators + rclcpp - - - - TODO + std_msgs + geometry_msgs + sensor_msgs + tf2 + tf2_ros + rosidl_default_runtime + ros2launch + rosidl_interface_packages - - - - + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - geometry_msgs - message_generation - roscpp - sensor_msgs - std_msgs - tf2 - tf2_ros - geometry_msgs - roscpp - sensor_msgs - std_msgs - tf2 - tf2_ros - geometry_msgs - roscpp - sensor_msgs - std_msgs - tf2 - tf2_ros - - - - - + ament_cmake diff --git a/ros/daemon_ros_client/src/DaemonRosClientNode.cpp b/ros/daemon_ros_client/src/DaemonRosClientNode.cpp index c6b0da68..5c19c536 100644 --- a/ros/daemon_ros_client/src/DaemonRosClientNode.cpp +++ b/ros/daemon_ros_client/src/DaemonRosClientNode.cpp @@ -2,25 +2,38 @@ #include "QtUtils.h" -DaemonRosClientNode::DaemonRosClientNode(int &argc, char* argv[], ros::NodeHandle& nodeHandle, DaemonRosClientNodeConfiguration configuration) - : QCoreApplication(argc, argv), m_websocketProtocolWrapper(nullptr), m_nodeHandle(nodeHandle), m_configuration(move(configuration)) +DaemonRosClientNode::DaemonRosClientNode() : rclcpp::Node("daemon_ros_client_node"), m_tfBroadcaster(*this) { - initWebSocketProtocolWrapper(); + m_baseLinkTorsoBaseDeltaZ = declare_parameter("base_link_torso_base_delta_z", 0.0); + initROS(); + initWebSocketProtocolWrapper(); } void DaemonRosClientNode::initROS() { - m_baseStatusPub = m_nodeHandle.advertise("daemon/base_status", PubQueueSize); - m_startButtonPressedPub = m_nodeHandle.advertise("daemon/start_button_pressed", PubQueueSize); - m_stopButtonPressedPub = m_nodeHandle.advertise("daemon/stop_button_pressed", PubQueueSize); - m_imuPub = m_nodeHandle.advertise("daemon/imu/data_raw", PubQueueSize); - m_motorStatusPub = m_nodeHandle.advertise("daemon/motor_status", PubQueueSize); - - m_setVolumeSub = m_nodeHandle.subscribe("daemon/set_volume", SubQueueSize, &DaemonRosClientNode::setVolumeCallback, this); - m_setLedColorsSub = m_nodeHandle.subscribe("daemon/set_led_colors", SubQueueSize, &DaemonRosClientNode::setLedColorsCallback, this); - m_setTorsoOrientationSub = m_nodeHandle.subscribe("daemon/set_torso_orientation", SubQueueSize, &DaemonRosClientNode::setTorsoOrientationCallback, this); - m_setHeadPoseSub = m_nodeHandle.subscribe("daemon/set_head_pose", SubQueueSize, &DaemonRosClientNode::setHeadPoseCallback, this); + m_baseStatusPub = create_publisher("daemon/base_status", PubQueueSize); + m_startButtonPressedPub = create_publisher("daemon/start_button_pressed", PubQueueSize); + m_stopButtonPressedPub = create_publisher("daemon/stop_button_pressed", PubQueueSize); + m_imuPub = create_publisher("daemon/imu/data_raw", PubQueueSize); + m_motorStatusPub = create_publisher("daemon/motor_status", PubQueueSize); + + m_setVolumeSub = create_subscription( + "daemon/set_volume", + SubQueueSize, + [this](const std_msgs::msg::UInt8::SharedPtr msg) { setVolumeCallback(msg); }); + m_setLedColorsSub = create_subscription( + "daemon/set_led_colors", + SubQueueSize, + [this](const daemon_ros_client::msg::LedColors::SharedPtr msg) { setLedColorsCallback(msg); }); + m_setTorsoOrientationSub = create_subscription( + "daemon/set_torso_orientation", + SubQueueSize, + [this](const std_msgs::msg::Float32::SharedPtr msg) { setTorsoOrientationCallback(msg); }); + m_setHeadPoseSub = create_subscription( + "daemon/set_head_pose", + SubQueueSize, + [this](const geometry_msgs::msg::PoseStamped::SharedPtr msg) { setHeadPoseCallback(msg); }); } void DaemonRosClientNode::initWebSocketProtocolWrapper() @@ -30,13 +43,33 @@ void DaemonRosClientNode::initWebSocketProtocolWrapper() // Connect only useful signals // WARNING Using direct connection, handleXXX functions must be thread safe) - connect(m_websocketProtocolWrapper, &WebSocketProtocolWrapper::newBaseStatus, this, &DaemonRosClientNode::handleBaseStatus, Qt::DirectConnection); - connect(m_websocketProtocolWrapper, &WebSocketProtocolWrapper::newButtonPressed, this, &DaemonRosClientNode::handleButtonPressed, Qt::DirectConnection); - connect(m_websocketProtocolWrapper, &WebSocketProtocolWrapper::newImuData, this, &DaemonRosClientNode::handleImuData, Qt::DirectConnection); - connect(m_websocketProtocolWrapper, &WebSocketProtocolWrapper::newMotorStatus, this, &DaemonRosClientNode::handleMotorStatus, Qt::DirectConnection); + connect( + m_websocketProtocolWrapper, + &WebSocketProtocolWrapper::newBaseStatus, + this, + &DaemonRosClientNode::handleBaseStatus, + Qt::DirectConnection); + connect( + m_websocketProtocolWrapper, + &WebSocketProtocolWrapper::newButtonPressed, + this, + &DaemonRosClientNode::handleButtonPressed, + Qt::DirectConnection); + connect( + m_websocketProtocolWrapper, + &WebSocketProtocolWrapper::newImuData, + this, + &DaemonRosClientNode::handleImuData, + Qt::DirectConnection); + connect( + m_websocketProtocolWrapper, + &WebSocketProtocolWrapper::newMotorStatus, + this, + &DaemonRosClientNode::handleMotorStatus, + Qt::DirectConnection); } -void DaemonRosClientNode::setVolumeCallback(const std_msgs::UInt8::ConstPtr& msg) +void DaemonRosClientNode::setVolumeCallback(const std_msgs::msg::UInt8::SharedPtr& msg) { SetVolumePayload payload; payload.volume = msg->data; @@ -51,10 +84,10 @@ void DaemonRosClientNode::setVolumeCallback(const std_msgs::UInt8::ConstPtr& msg }); } -void DaemonRosClientNode::setLedColorsCallback(const daemon_ros_client::LedColors::ConstPtr& msg) +void DaemonRosClientNode::setLedColorsCallback(const daemon_ros_client::msg::LedColors::SharedPtr& msg) { SetLedColorsPayload payload; - for (size_t i = 0; i < SetLedColorsPayload::LED_COUNT; i++) + for (size_t i = 0; i < SetLedColorsPayload::LED_COUNT; i++) { payload.colors[i].red = msg->colors[i].red; payload.colors[i].green = msg->colors[i].green; @@ -71,7 +104,7 @@ void DaemonRosClientNode::setLedColorsCallback(const daemon_ros_client::LedColor }); } -void DaemonRosClientNode::setTorsoOrientationCallback(const std_msgs::Float32::ConstPtr& msg) +void DaemonRosClientNode::setTorsoOrientationCallback(const std_msgs::msg::Float32::SharedPtr& msg) { SetTorsoOrientationPayload payload; payload.torsoOrientation = msg->data; @@ -86,11 +119,11 @@ void DaemonRosClientNode::setTorsoOrientationCallback(const std_msgs::Float32::C }); } -void DaemonRosClientNode::setHeadPoseCallback(const geometry_msgs::PoseStamped::ConstPtr& msg) +void DaemonRosClientNode::setHeadPoseCallback(const geometry_msgs::msg::PoseStamped::SharedPtr& msg) { if (msg->header.frame_id != HEAD_POSE_FRAME_ID) { - ROS_ERROR_STREAM("Invalid head pose frame id (" << msg->header.frame_id << ")"); + RCLCPP_ERROR_STREAM(get_logger(), "Invalid head pose frame id (" << msg->header.frame_id << ")"); return; } @@ -116,8 +149,8 @@ void DaemonRosClientNode::setHeadPoseCallback(const geometry_msgs::PoseStamped:: void DaemonRosClientNode::handleBaseStatus(Device source, const BaseStatusPayload& payload) { // WARNING must be tread safe, called from Qt Thread - daemon_ros_client::BaseStatus msg; - msg.header.stamp = ros::Time::now(); + daemon_ros_client::msg::BaseStatus msg; + msg.header.stamp = get_clock()->now(); msg.is_psu_connected = payload.isPsuConnected; msg.has_charger_error = payload.hasChargerError; msg.is_battery_charging = payload.isBatteryCharging; @@ -134,7 +167,7 @@ void DaemonRosClientNode::handleBaseStatus(Device source, const BaseStatusPayloa msg.volume = payload.volume; msg.maximum_volume = payload.maximumVolume; - m_baseStatusPub.publish(msg); + m_baseStatusPub->publish(msg); } void DaemonRosClientNode::handleButtonPressed(Device source, const ButtonPressedPayload& payload) @@ -143,13 +176,13 @@ void DaemonRosClientNode::handleButtonPressed(Device source, const ButtonPressed switch (payload.button) { case Button::START: - m_startButtonPressedPub.publish(std_msgs::Empty()); + m_startButtonPressedPub->publish(std_msgs::msg::Empty()); break; case Button::STOP: - m_stopButtonPressedPub.publish(std_msgs::Empty()); + m_stopButtonPressedPub->publish(std_msgs::msg::Empty()); break; default: - ROS_ERROR_STREAM("Not handled buttons (" << static_cast(payload.button) << ")"); + RCLCPP_ERROR_STREAM(get_logger(), "Not handled buttons (" << static_cast(payload.button) << ")"); break; } } @@ -157,31 +190,31 @@ void DaemonRosClientNode::handleButtonPressed(Device source, const ButtonPressed void DaemonRosClientNode::handleImuData(Device source, const ImuDataPayload& payload) { // WARNING must be tread safe, called from Qt Thread - sensor_msgs::Imu msg; - msg.header.stamp = ros::Time::now(); + sensor_msgs::msg::Imu msg; + msg.header.stamp = get_clock()->now(); msg.header.frame_id = "dynamixel_control_imu"; msg.orientation.x = 0; msg.orientation.y = 0; msg.orientation.z = 0; msg.orientation.w = 0; - msg.orientation_covariance.assign(-1.0); + msg.orientation_covariance.fill(-1.0); msg.angular_velocity.x = payload.angularRateX; msg.angular_velocity.y = payload.angularRateY; msg.angular_velocity.z = payload.angularRateZ; - msg.angular_velocity_covariance.assign(0.0); + msg.angular_velocity_covariance.fill(0.0); msg.linear_acceleration.x = payload.accelerationX; msg.linear_acceleration.y = payload.accelerationY; msg.linear_acceleration.z = payload.accelerationZ; - msg.linear_acceleration_covariance.assign(0.0); + msg.linear_acceleration_covariance.fill(0.0); - m_imuPub.publish(msg); + m_imuPub->publish(msg); } void DaemonRosClientNode::handleMotorStatus(Device source, const MotorStatusPayload& payload) { // WARNING must be tread safe, called from Qt Thread - daemon_ros_client::MotorStatus msg; - msg.header.stamp = ros::Time::now(); + daemon_ros_client::msg::MotorStatus msg; + msg.header.stamp = get_clock()->now(); msg.torso_orientation = payload.torsoOrientation; msg.torso_servo_speed = payload.torsoServoSpeed; @@ -210,19 +243,19 @@ void DaemonRosClientNode::handleMotorStatus(Device source, const MotorStatusPayl sendTorsoTf(msg.header.stamp, msg.torso_orientation); sendHeadTf(msg.header.stamp, msg.head_pose); - m_motorStatusPub.publish(msg); + m_motorStatusPub->publish(msg); } -void DaemonRosClientNode::sendTorsoTf(const ros::Time& stamp, float torsoOrientation) +void DaemonRosClientNode::sendTorsoTf(const rclcpp::Time& stamp, float torsoOrientation) { - geometry_msgs::TransformStamped transformStamped; + geometry_msgs::msg::TransformStamped transformStamped; transformStamped.header.stamp = stamp; transformStamped.header.frame_id = "base_link"; transformStamped.child_frame_id = "torso_base"; transformStamped.transform.translation.x = 0; transformStamped.transform.translation.y = 0; - transformStamped.transform.translation.z = m_configuration.baseLinkTorsoBaseDeltaZ; + transformStamped.transform.translation.z = m_baseLinkTorsoBaseDeltaZ; tf2::Quaternion q; q.setRPY(0, 0, torsoOrientation); @@ -234,9 +267,9 @@ void DaemonRosClientNode::sendTorsoTf(const ros::Time& stamp, float torsoOrienta m_tfBroadcaster.sendTransform(transformStamped); } -void DaemonRosClientNode::sendHeadTf(const ros::Time& stamp, const geometry_msgs::Pose& pose) +void DaemonRosClientNode::sendHeadTf(const rclcpp::Time& stamp, const geometry_msgs::msg::Pose& pose) { - geometry_msgs::TransformStamped transformStamped; + geometry_msgs::msg::TransformStamped transformStamped; transformStamped.header.stamp = stamp; transformStamped.header.frame_id = HEAD_POSE_FRAME_ID; @@ -256,7 +289,7 @@ void DaemonRosClientNode::sendHeadTf(const ros::Time& stamp, const geometry_msgs void DaemonRosClientNode::cleanup() { SetLedColorsPayload payload; - for (size_t i = 0; i < SetLedColorsPayload::LED_COUNT; i++) + for (size_t i = 0; i < SetLedColorsPayload::LED_COUNT; i++) { payload.colors[i].red = 0; payload.colors[i].green = 0; diff --git a/ros/daemon_ros_client/src/DaemonRosClientNode.h b/ros/daemon_ros_client/src/DaemonRosClientNode.h index 4a514fc8..cdee2545 100644 --- a/ros/daemon_ros_client/src/DaemonRosClientNode.h +++ b/ros/daemon_ros_client/src/DaemonRosClientNode.h @@ -1,24 +1,23 @@ #ifndef _DAEMON_ROS_CLIENT_NODE_H_ #define _DAEMON_ROS_CLIENT_NODE_H_ -#include #include "WebSocketProtocolWrapper.h" -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include @@ -29,59 +28,45 @@ constexpr uint32_t PubQueueSize = 1; constexpr uint32_t SubQueueSize = 10; constexpr const char* HEAD_POSE_FRAME_ID = "stewart_base"; -struct DaemonRosClientNodeConfiguration -{ - double baseLinkTorsoBaseDeltaZ; - - DaemonRosClientNodeConfiguration() : baseLinkTorsoBaseDeltaZ(0.0) - { - - } -}; - -class DaemonRosClientNode : public QCoreApplication +class DaemonRosClientNode : public QObject, public rclcpp::Node { + Q_OBJECT - WebSocketProtocolWrapper *m_websocketProtocolWrapper; + double m_baseLinkTorsoBaseDeltaZ; - ros::NodeHandle& m_nodeHandle; - DaemonRosClientNodeConfiguration m_configuration; + WebSocketProtocolWrapper* m_websocketProtocolWrapper; - ros::Publisher m_baseStatusPub; - ros::Publisher m_startButtonPressedPub; - ros::Publisher m_stopButtonPressedPub; - ros::Publisher m_imuPub; - ros::Publisher m_motorStatusPub; + rclcpp::Publisher::SharedPtr m_baseStatusPub; + rclcpp::Publisher::SharedPtr m_startButtonPressedPub; + rclcpp::Publisher::SharedPtr m_stopButtonPressedPub; + rclcpp::Publisher::SharedPtr m_imuPub; + rclcpp::Publisher::SharedPtr m_motorStatusPub; - ros::Subscriber m_setVolumeSub; - ros::Subscriber m_setLedColorsSub; - ros::Subscriber m_setTorsoOrientationSub; - ros::Subscriber m_setHeadPoseSub; + rclcpp::Subscription::SharedPtr m_setVolumeSub; + rclcpp::Subscription::SharedPtr m_setLedColorsSub; + rclcpp::Subscription::SharedPtr m_setTorsoOrientationSub; + rclcpp::Subscription::SharedPtr m_setHeadPoseSub; tf2_ros::TransformBroadcaster m_tfBroadcaster; - Q_OBJECT - - public: - - DaemonRosClientNode(int &argc, char* argv[], ros::NodeHandle& nodeHandle, DaemonRosClientNodeConfiguration configuration); +public: + DaemonRosClientNode(); void cleanup(); - private: - +private: void initROS(); void initWebSocketProtocolWrapper(); - void setVolumeCallback(const std_msgs::UInt8::ConstPtr& msg); - void setLedColorsCallback(const daemon_ros_client::LedColors::ConstPtr& msg); - void setTorsoOrientationCallback(const std_msgs::Float32::ConstPtr& msg); - void setHeadPoseCallback(const geometry_msgs::PoseStamped::ConstPtr& msg); + void setVolumeCallback(const std_msgs::msg::UInt8::SharedPtr& msg); + void setLedColorsCallback(const daemon_ros_client::msg::LedColors::SharedPtr& msg); + void setTorsoOrientationCallback(const std_msgs::msg::Float32::SharedPtr& msg); + void setHeadPoseCallback(const geometry_msgs::msg::PoseStamped::SharedPtr& msg); void handleBaseStatus(Device source, const BaseStatusPayload& payload); void handleButtonPressed(Device source, const ButtonPressedPayload& payload); void handleImuData(Device source, const ImuDataPayload& payload); void handleMotorStatus(Device source, const MotorStatusPayload& payload); - void sendTorsoTf(const ros::Time& stamp, float torsoOrientation); - void sendHeadTf(const ros::Time& stamp, const geometry_msgs::Pose& pose); + void sendTorsoTf(const rclcpp::Time& stamp, float torsoOrientation); + void sendHeadTf(const rclcpp::Time& stamp, const geometry_msgs::msg::Pose& pose); }; -#endif //_DAEMON_ROS_CLIENT_NODE_H_ +#endif //_DAEMON_ROS_CLIENT_NODE_H_ diff --git a/ros/daemon_ros_client/src/daemon_ros_client_node.cpp b/ros/daemon_ros_client/src/daemon_ros_client_node.cpp index 462e888c..ec69e922 100644 --- a/ros/daemon_ros_client/src/daemon_ros_client_node.cpp +++ b/ros/daemon_ros_client/src/daemon_ros_client_node.cpp @@ -1,5 +1,8 @@ #include "DaemonRosClientNode.h" + +#include + #include #include @@ -28,31 +31,27 @@ void catchUnixSignals(std::initializer_list quitSignals) int main(int argc, char** argv) { - ros::init(argc, argv, "daemon_ros_client_node"); + QCoreApplication app(argc, argv); - ros::NodeHandle nodeHandle; - ros::NodeHandle privateNodeHandle("~"); + rclcpp::init(argc, argv); - DaemonRosClientNodeConfiguration configuration; + auto node = std::make_shared(); - if (!privateNodeHandle.getParam("base_link_torso_base_delta_z", configuration.baseLinkTorsoBaseDeltaZ)) - { - ROS_ERROR("The parameter base_link_torso_base_delta_z is required."); - return -1; - } + catchUnixSignals({SIGQUIT, SIGINT, SIGTERM, SIGHUP}); // Run ROS in background - ros::AsyncSpinner spinner(1); - spinner.start(); - - catchUnixSignals({SIGQUIT, SIGINT, SIGTERM, SIGHUP}); + rclcpp::executors::SingleThreadedExecutor rosExecutor; + rosExecutor.add_node(node); + std::thread spinThread([&rosExecutor]() { rosExecutor.spin(); }); // Initialize and start Qt App - DaemonRosClientNode app(argc, argv, nodeHandle, configuration); - app.exec(); + int returnCode = app.exec(); + + node->cleanup(); + rosExecutor.cancel(); + spinThread.join(); - app.cleanup(); + rclcpp::shutdown(); - // Stop ROS spinner - spinner.stop(); + return returnCode; } diff --git a/ros/demos/connect4/CMakeLists.txt b/ros/demos/connect4/CMakeLists.txt index 6e43d399..30e54162 100644 --- a/ros/demos/connect4/CMakeLists.txt +++ b/ros/demos/connect4/CMakeLists.txt @@ -1,158 +1,40 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.8) project(connect4) -## Set compile options -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - daemon_ros_client - hbba_lite - roscpp - sensor_msgs - t_top_hbba_lite - opentera_webrtc_ros_msgs - led_animations - daemon_ros_client - opentera_webrtc_ros - opentera_webrtc_ros_msgs - tf - t_top - std_msgs - geometry_msgs - video_analyzer -) - -## System dependencies are found with CMake's conventions - -add_compile_definitions(WEBRTC_POSIX QT_NO_KEYWORDS) - -set(connect4_qt_components Core Widgets Network WebSockets) -find_package(Qt5 COMPONENTS ${connect4_qt_components} REQUIRED) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -# add_message_files( -# FILES -# Message1.msg -# Message2.msg -# ) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -# generate_messages( -# DEPENDENCIES -# sensor_msgs -# ) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( -# INCLUDE_DIRS include -# LIBRARIES connect4 -# CATKIN_DEPENDS daemon_ros_client hbba_lite roscpp sensor_msgs t_top_hbba_lite -# DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( -# include - ${catkin_INCLUDE_DIRS} -) - -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/connect4.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# find dependencies +find_package(ament_cmake REQUIRED) +find_package(daemon_ros_client REQUIRED) +find_package(sensor_msgs REQUIRED) +find_package(rclcpp REQUIRED) +find_package(rclpy REQUIRED) +find_package(t_top_hbba_lite REQUIRED) +find_package(tf2 REQUIRED) +find_package(tf2_ros REQUIRED) +find_package(perception_msgs REQUIRED) +find_package(geometry_msgs REQUIRED) +find_package(opentera_webrtc_ros_msgs REQUIRED) + +set(connect4_components Core Widgets Gui WebSockets Network) +find_package(Qt5 COMPONENTS ${connect4_components} REQUIRED) + +# C++ Nodes set(moc_headers - src/ImageDisplay.h src/Connect4Widget.h + src/ImageDisplay.h ) set(other_headers @@ -168,76 +50,35 @@ set(srcs qt5_wrap_cpp(project_moc_srcs ${moc_headers}) add_executable(${PROJECT_NAME}_node ${srcs} ${uis} ${moc_headers} ${other_headers} ${project_moc_uis} ${project_moc_srcs}) -qt5_use_modules(${PROJECT_NAME}_node ${connect4_qt_components}) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -target_link_libraries(${PROJECT_NAME}_node - ${catkin_LIBRARIES} - ${connect4_qt_components_link} +qt5_use_modules(${PROJECT_NAME}_node ${connect4_components}) +ament_target_dependencies(${PROJECT_NAME}_node + rclcpp + t_top_hbba_lite + perception_msgs + opentera_webrtc_ros_msgs ) +install(TARGETS ${PROJECT_NAME}_node DESTINATION lib/${PROJECT_NAME}) -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -catkin_install_python(PROGRAMS - scripts/nearest_face_orientation_node.py +# Python Nodes +install(PROGRAMS scripts/nearest_face_following_orientation_replication_node.py - DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} + scripts/nearest_face_orientation_node.py + DESTINATION lib/${PROJECT_NAME} ) -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_connect4.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() - -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +# Launch files +install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}) + +if(BUILD_TESTING) + find_package(ament_lint_auto REQUIRED) + # the following line skips the linter which checks for copyrights + # comment the line when a copyright and license is added to all source files + set(ament_cmake_copyright_FOUND TRUE) + # the following line skips cpplint (only works in a git repo) + # comment the line when this package is in a git repo and when + # a copyright and license is added to all source files + set(ament_cmake_cpplint_FOUND TRUE) + ament_lint_auto_find_test_dependencies() +endif() + +ament_package() diff --git a/ros/demos/connect4/launch/connect4.launch b/ros/demos/connect4/launch/connect4.launch.xml similarity index 65% rename from ros/demos/connect4/launch/connect4.launch rename to ros/demos/connect4/launch/connect4.launch.xml index 6696cfc3..9729fe2e 100644 --- a/ros/demos/connect4/launch/connect4.launch +++ b/ros/demos/connect4/launch/connect4.launch.xml @@ -9,26 +9,26 @@ - - - + + + - + - - - + + + - - - + + + @@ -42,17 +42,17 @@ - + - - - - + + + + - + @@ -63,9 +63,9 @@ - + - + @@ -81,38 +81,38 @@ - + - - - + + + - + - + - + - - + + - - + + diff --git a/ros/demos/connect4/launch/test_face_orientation.launch b/ros/demos/connect4/launch/test_face_orientation.launch.xml similarity index 75% rename from ros/demos/connect4/launch/test_face_orientation.launch rename to ros/demos/connect4/launch/test_face_orientation.launch.xml index 4bdcc63e..020b03bb 100644 --- a/ros/demos/connect4/launch/test_face_orientation.launch +++ b/ros/demos/connect4/launch/test_face_orientation.launch.xml @@ -1,29 +1,34 @@ - + - + - + - + - + + + + + + - + @@ -32,9 +37,9 @@ - + - + @@ -45,20 +50,17 @@ - - + - - + - diff --git a/ros/demos/connect4/package.xml b/ros/demos/connect4/package.xml index fda1b92a..4b99331e 100644 --- a/ros/demos/connect4/package.xml +++ b/ros/demos/connect4/package.xml @@ -1,104 +1,29 @@ - + + connect4 0.0.0 - The connect4 package + Connect4 game + Marc-Antoine Maheux + GPL-3.0 license + + ament_cmake + + daemon_ros_client + sensor_msgs + rclcpp + rclpy + t_top_hbba_lite + tf2 + tf2_ros + perception_msgs + geometry_msgs + opentera_webrtc_ros_msgs + + ament_lint_auto + ament_lint_common - - - - marc-antoine - - - - - - TODO - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - daemon_ros_client - hbba_lite - roscpp - sensor_msgs - t_top_hbba_lite - opentera_webrtc_ros_msgs - led_animations - daemon_ros_client - opentera_webrtc_ros - opentera_webrtc_ros_msgs - tf - t_top - std_msgs - geometry_msgs - video_analyzer - daemon_ros_client - hbba_lite - roscpp - sensor_msgs - t_top_hbba_lite - opentera_webrtc_ros_msgs - led_animations - daemon_ros_client - opentera_webrtc_ros - opentera_webrtc_ros_msgs - tf - t_top - std_msgs - geometry_msgs - video_analyzer - daemon_ros_client - hbba_lite - roscpp - sensor_msgs - t_top_hbba_lite - opentera_webrtc_ros_msgs - led_animations - daemon_ros_client - opentera_webrtc_ros - opentera_webrtc_ros_msgs - tf - t_top - std_msgs - geometry_msgs - video_analyzer - - - - - + ament_cmake diff --git a/ros/demos/connect4/scripts/nearest_face_following_orientation_replication_node.py b/ros/demos/connect4/scripts/nearest_face_following_orientation_replication_node.py index 8ca381c6..919079e5 100755 --- a/ros/demos/connect4/scripts/nearest_face_following_orientation_replication_node.py +++ b/ros/demos/connect4/scripts/nearest_face_following_orientation_replication_node.py @@ -5,10 +5,18 @@ import numpy as np -import rospy -import tf + +import rclpy +import rclpy.node +import rclpy.executors + +from tf2_ros import TransformException +from tf2_ros.buffer import Buffer +from tf2_ros.transform_listener import TransformListener +import tf2_geometry_msgs + from geometry_msgs.msg import PointStamped -from video_analyzer.msg import VideoAnalysis +from perception_msgs.msg import VideoAnalysis from std_msgs.msg import String from opentera_webrtc_ros_msgs.msg import PeerData @@ -18,47 +26,54 @@ PERSON_POSE_NOSE_INDEX = 0 -class NearestFaceFollowingOrientationReplicationNode: +class NearestFaceFollowingOrientationReplicationNode(rclpy.node.Node): def __init__(self): - self._simulation = rospy.get_param('~simulation') - self._rate = rospy.Rate(rospy.get_param('~control_frequency')) - self._torso_control_alpha = rospy.get_param('~torso_control_alpha') - self._head_control_alpha = rospy.get_param('~head_control_alpha') - self._head_control_pitch_up_alpha_gain = rospy.get_param('~head_control_pitch_up_alpha_gain') - self._min_head_roll = rospy.get_param('~min_head_roll_rad') - self._max_head_roll = rospy.get_param('~max_head_roll_rad') - self._min_head_pitch = rospy.get_param('~min_head_pitch_rad') - self._max_head_pitch = rospy.get_param('~max_head_pitch_rad') - - self._nose_confidence_threshold = rospy.get_param('~nose_confidence_threshold') + super().__init__('nearest_face_following_orientation_replication_node') + self._simulation = self.declare_parameter('simulation', False).get_parameter_value().bool_value + self._control_frequency = self.declare_parameter('control_frequency', 30.0).get_parameter_value().double_value + self._torso_control_alpha = self.declare_parameter('torso_control_alpha', 0.2).get_parameter_value().double_value + self._head_control_alpha = self.declare_parameter('head_control_alpha', 0.1).get_parameter_value().double_value + self._head_control_pitch_up_alpha_gain = self.declare_parameter('head_control_pitch_up_alpha_gain', 2.0).get_parameter_value().double_value + self._min_head_roll = self.declare_parameter('min_head_roll_rad', -0.3).get_parameter_value().double_value + self._max_head_roll = self.declare_parameter('max_head_roll_rad', 0.3).get_parameter_value().double_value + self._min_head_pitch = self.declare_parameter('min_head_pitch_rad', -0.15).get_parameter_value().double_value + self._max_head_pitch = self.declare_parameter('max_head_pitch_rad', 0.3).get_parameter_value().double_value + self._nose_confidence_threshold = self.declare_parameter('nose_confidence_threshold', 0.4).get_parameter_value().double_value self._target_lock = threading.Lock() self._target_torso_yaw = None self._target_head_roll = 0.0 self._target_head_pitch = 0.0 - self._movement_commands = MovementCommands(self._simulation, 'other') + self._movement_commands = MovementCommands(self, self._simulation, 'other') + + self._tf_buffer = Buffer() + self._tf_listener = TransformListener(self._tf_buffer, self) - self._tf_listener = tf.TransformListener() - self._video_analysis_sub = rospy.Subscriber('video_analysis', VideoAnalysis, self._video_analysis_cb, queue_size=1) - self._face_orientation_sub = rospy.Subscriber('face_orientation', String, self._face_orientation_cb, queue_size=1) - self._face_orientation_peer_data_sub = rospy.Subscriber('face_orientation_peer_data', PeerData, self._face_orientation_cb, queue_size=1) + self._video_analysis_sub = self.create_subscription(VideoAnalysis, 'video_analysis', self._video_analysis_cb, 1) + self._face_orientation_sub = self.create_subscription(String, 'face_orientation', self._face_orientation_cb, 1) + self._face_orientation_peer_data_sub = self.create_subscription(PeerData, 'face_orientation_peer_data', self._face_orientation_cb, 1) + + self._timer = self.create_timer(1 / self._control_frequency, self._timer_callback) def _video_analysis_cb(self, msg): if self._movement_commands.is_filtering_all_messages: return if not msg.contains_3d_positions: - rospy.logerr('The video analysis must contain 3d positions.') + self.get_logger().error('The video analysis must contain 3d positions.') return - face_position = self._find_nearest_face_position(msg.objects, msg.header) - if face_position is None: - return + try: + face_position = self._find_nearest_face_position(msg.objects, msg.header) + if face_position is None: + return - target_torso_yaw, _ = vector_to_angles(face_position) - if math.isfinite(target_torso_yaw): - with self._target_lock: - self._target_torso_yaw = target_torso_yaw + target_torso_yaw, _ = vector_to_angles(face_position) + if math.isfinite(target_torso_yaw): + with self._target_lock: + self._target_torso_yaw = target_torso_yaw + except TransformException as e: + self.get_logger().error(f'Could not transform: {e}') def _find_nearest_face_position(self, objects, header): nose_points_3d = [] @@ -85,7 +100,8 @@ def _transform_point(self, point, header): temp_in_point.point.y = point.y temp_in_point.point.z = point.z - base_link_point = self._tf_listener.transformPoint('/base_link', temp_in_point) + transform = self._tf_buffer.lookup_transform('base_link', header.frame_id, rclpy.time.Time.from_msg(header.stamp)) + base_link_point = tf2_geometry_msgs.do_transform_point(temp_in_point, transform) point.x = base_link_point.point.x point.y = base_link_point.point.y @@ -94,7 +110,7 @@ def _transform_point(self, point, header): def _face_orientation_cb(self, msg): fields = msg.data.split(',') if len(fields) != 2: - rospy.logerr('Invalid face orientation message') + self.get_logger().error('Invalid face orientation message') return roll = np.clip(float(fields[0]), self._min_head_roll, self._max_head_roll) @@ -104,14 +120,12 @@ def _face_orientation_cb(self, msg): self._target_head_roll = roll self._target_head_pitch = pitch - def run(self): - while not rospy.is_shutdown(): - self._rate.sleep() - if self._movement_commands.is_filtering_all_messages: - continue + def _timer_callback(self): + if self._movement_commands.is_filtering_all_messages: + return - self._update_torso() - self._update_head() + self._update_torso() + self._update_head() def _update_torso(self): with self._target_lock: @@ -146,15 +160,24 @@ def _update_head(self): self._movement_commands.move_head([0, 0, HEAD_ZERO_Z, roll, pitch, 0]) + def run(self): + executor = rclpy.executors.MultiThreadedExecutor(num_threads=2) + executor.add_node(self) + executor.spin() def main(): - rospy.init_node('nearest_face_following_orientation_replication_node') + rclpy.init() nearest_face_following_orientation_replication_node = NearestFaceFollowingOrientationReplicationNode() - nearest_face_following_orientation_replication_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + nearest_face_following_orientation_replication_node.run() + except KeyboardInterrupt: pass + finally: + nearest_face_following_orientation_replication_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/demos/connect4/scripts/nearest_face_orientation_node.py b/ros/demos/connect4/scripts/nearest_face_orientation_node.py index 876464f0..03260136 100755 --- a/ros/demos/connect4/scripts/nearest_face_orientation_node.py +++ b/ros/demos/connect4/scripts/nearest_face_orientation_node.py @@ -5,10 +5,16 @@ import numpy as np from scipy.spatial.transform import Rotation as R -import rospy -import tf +import rclpy +import rclpy.node + +from tf2_ros import TransformException +from tf2_ros.buffer import Buffer +from tf2_ros.transform_listener import TransformListener +import tf2_geometry_msgs + from geometry_msgs.msg import PointStamped, Point, Vector3 -from video_analyzer.msg import VideoAnalysis +from perception_msgs.msg import VideoAnalysis from std_msgs.msg import String from t_top import vector_to_angles @@ -19,30 +25,36 @@ PERSON_POSE_RIGHT_EYE_INDEX = 2 -class NearestFaceOrientationNode: +class NearestFaceOrientationNode(rclpy.node.Node): def __init__(self): - self._nose_confidence_threshold = rospy.get_param('~nose_confidence_threshold') - self._pitch_offset_rad = rospy.get_param('~pitch_offset_rad') - self._filter_alpha = rospy.get_param('~filter_alpha') - self._roll_dead_zone = rospy.get_param('~roll_dead_zone') + super().__init__('nearest_face_orientation_node') + + self._nose_confidence_threshold = self.declare_parameter('nose_confidence_threshold', 0.4).get_parameter_value().double_value + self._pitch_offset_rad = self.declare_parameter('pitch_offset_rad', -0.8).get_parameter_value().double_value + self._filter_alpha = self.declare_parameter('filter_alpha', 0.65).get_parameter_value().double_value + self._roll_dead_zone = self.declare_parameter('roll_dead_zone', 0.05).get_parameter_value().double_value self._roll = 0.0 self._pitch = 0.0 - self._tf_listener = tf.TransformListener() + self._tf_buffer = Buffer() + self._tf_listener = TransformListener(self._tf_buffer, self) - self._face_orientation_pub = rospy.Publisher('face_orientation', String, queue_size=1) - self._video_analysis_sub = rospy.Subscriber('video_analysis', VideoAnalysis, self._video_analysis_cb, queue_size=1) + self._face_orientation_pub = self.create_publisher(String, 'face_orientation', 1) + self._video_analysis_sub = self.create_subscription(VideoAnalysis, 'video_analysis', self._video_analysis_cb, 1) def _video_analysis_cb(self, msg): if not msg.contains_3d_positions: - rospy.logerr('The video analysis must contain 3d positions.') + self.get_logger().error('The video analysis must contain 3d positions.') return - self._update_nearest_face_orientation(msg.objects, msg.header) - msg = String() - msg.data = f'{self._roll},{self._pitch}' - self._face_orientation_pub.publish(msg) + try: + self._update_nearest_face_orientation(msg.objects, msg.header) + msg = String() + msg.data = f'{self._roll},{self._pitch}' + self._face_orientation_pub.publish(msg) + except TransformException as e: + self.get_logger().error(f'Could not transform: {e}') def _update_nearest_face_orientation(self, objects, header): poses = [] @@ -97,7 +109,8 @@ def _transform_point(self, point, header): temp_in_point.point.y = point.y temp_in_point.point.z = point.z - stewart_base_point = self._tf_listener.transformPoint('/stewart_base', temp_in_point) + transform = self._tf_buffer.lookup_transform('stewart_base', header.frame_id, rclpy.time.Time.from_msg(header.stamp)) + stewart_base_point = tf2_geometry_msgs.do_transform_point(temp_in_point, transform) point.x = stewart_base_point.point.x point.y = stewart_base_point.point.y @@ -113,7 +126,7 @@ def _vector_from_to(self, from_p, to_p): def _vector_to_yaw(self, vector): vector = np.array([vector.x, vector.y, vector.z]) vector /= np.linalg.norm(vector) - + return np.arctan2(vector[0], vector[1]) def _rotate_point_yaw(self, point, yaw): @@ -141,17 +154,22 @@ def _vector_to_roll_pitch(self, vector): return roll, pitch def run(self): - rospy.spin() + rclpy.spin(self) def main(): - rospy.init_node('nearest_face_orientation_node') + rclpy.init() nearest_face_orientation_node = NearestFaceOrientationNode() - nearest_face_orientation_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + nearest_face_orientation_node.run() + except KeyboardInterrupt: pass + finally: + nearest_face_orientation_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/demos/connect4/src/Connect4Widget.cpp b/ros/demos/connect4/src/Connect4Widget.cpp index 52af1ec1..de74658e 100644 --- a/ros/demos/connect4/src/Connect4Widget.cpp +++ b/ros/demos/connect4/src/Connect4Widget.cpp @@ -2,7 +2,6 @@ #include "QtUtils.h" #include -#include #include #include @@ -14,12 +13,11 @@ constexpr float ENABLED_VOLUME = 1; constexpr float DISABLED_VOLUME = 0; constexpr int SET_VOLUME_TIMER_INTERVAL_MS = 500; - constexpr int WEB_SOCKET_STATUS_TIMEOUT_MS = 1000; -Connect4Widget::Connect4Widget(ros::NodeHandle& nodeHandle, std::shared_ptr desireSet, QWidget* parent) - : m_nodeHandle(nodeHandle), +Connect4Widget::Connect4Widget(rclcpp::Node::SharedPtr node, std::shared_ptr desireSet, QWidget* parent) + : m_node(std::move(node)), m_desireSet(std::move(desireSet)), m_enabled(false), m_connect4ManagerConnectionRequested(false) @@ -29,20 +27,33 @@ Connect4Widget::Connect4Widget(ros::NodeHandle& nodeHandle, std::shared_ptraddWidget(m_imageDisplay); setLayout(layout); - m_startButtonPressedSub = - m_nodeHandle.subscribe("daemon/start_button_pressed", 1, &Connect4Widget::startButtonPressedCallback, this); - m_stopButtonPressedSub = - m_nodeHandle.subscribe("daemon/stop_button_pressed", 1, &Connect4Widget::stopButtonPressedCallback, this); - m_remoteImageSub = m_nodeHandle.subscribe("/webrtc_image", 1, &Connect4Widget::remoteImageCallback, this); + m_startButtonPressedSub = m_node->create_subscription( + "daemon/start_button_pressed", + 1, + [this](const std_msgs::msg::Empty::SharedPtr msg) { startButtonPressedCallback(msg); }); + m_stopButtonPressedSub = m_node->create_subscription( + "daemon/stop_button_pressed", + 1, + [this](const std_msgs::msg::Empty::SharedPtr msg) { stopButtonPressedCallback(msg); }); + + m_remoteImageSub = m_node->create_subscription( + "webrtc_image", + 1, + [this](const opentera_webrtc_ros_msgs::msg::PeerImage::SharedPtr msg) { remoteImageCallback(msg); }); + + m_openteraEventSubscriber = m_node->create_subscription( + "events", + 1, + [this](const opentera_webrtc_ros_msgs::msg::OpenTeraEvent::SharedPtr msg) { openteraEventCallback(msg); }); + - m_volumePub = m_nodeHandle.advertise("volume", 1); + + m_volumePub = m_node->create_publisher("volume", 1); m_setVolumeTimer = new QTimer(this); connect(m_setVolumeTimer, &QTimer::timeout, this, &Connect4Widget::onSetVolumeTimerTimeout); m_setVolumeTimer->start(SET_VOLUME_TIMER_INTERVAL_MS); - m_openteraEventSubscriber = m_nodeHandle.subscribe("events", 10, &Connect4Widget::openteraEventCallback, this); - m_connect4ManagerWebSocketTimer = new QTimer(this); connect(m_connect4ManagerWebSocketTimer, &QTimer::timeout, this, &Connect4Widget::onConnect4ManagerWebSocketTimeout); m_connect4ManagerWebSocketTimer->start(WEB_SOCKET_STATUS_TIMEOUT_MS); @@ -91,12 +102,12 @@ void Connect4Widget::onConnect4ManagerWebSocketSslErrors(const QList& { errorString += error.errorString() + ", "; } - ROS_ERROR_STREAM("Connect 4 manager web socket SSL errors: " << errorString.toStdString()); + RCLCPP_ERROR_STREAM(m_node->get_logger(), "Connect 4 manager web socket SSL errors: " << errorString.toStdString()); } void Connect4Widget::onConnect4ManagerWebSocketConnected() { - ROS_INFO("Connect 4 manager web socket connected"); + RCLCPP_INFO(m_node->get_logger(), "Connect 4 manager web socket connected"); QJsonObject dataObject; dataObject.insert("participant_name", m_observedParticipantName); @@ -105,24 +116,25 @@ void Connect4Widget::onConnect4ManagerWebSocketConnected() void Connect4Widget::onConnect4ManagerWebSocketDisconnected() { - ROS_INFO("Connect 4 manager web socket disconnected"); + RCLCPP_INFO(m_node->get_logger(), "Connect 4 manager web socket disconnected"); } void Connect4Widget::onConnect4ManagerWebSocketErrorOccurred(QAbstractSocket::SocketError error) { - ROS_ERROR_STREAM("Connect 4 manager web socket error: " << + RCLCPP_ERROR_STREAM(m_node->get_logger(), "Connect 4 manager web socket error: " << QMetaEnum::fromType().valueToKey(error)); } void Connect4Widget::onConnect4ManagerWebSocketTextMessageReceived(const QString& message) { - ROS_INFO_STREAM("Connect 4 manager web socket message: " << message.toStdString()); + RCLCPP_INFO_STREAM(m_node->get_logger(), "Connect 4 manager web socket message: " << message.toStdString()); QJsonParseError jsonParseError; QJsonDocument jsonMessage = QJsonDocument::fromJson(message.toUtf8(), &jsonParseError); if (jsonParseError.error != QJsonParseError::NoError) { - ROS_ERROR_STREAM("onnect 4 manager web socket message parsing error:" << jsonParseError.errorString().toStdString()); + RCLCPP_ERROR_STREAM(m_node->get_logger(), "Connect 4 manager web socket message parsing error: " << + jsonParseError.errorString().toStdString()); return; } @@ -132,7 +144,7 @@ void Connect4Widget::onConnect4ManagerWebSocketTextMessageReceived(const QString } } -void Connect4Widget::startButtonPressedCallback(const std_msgs::EmptyConstPtr& msg) +void Connect4Widget::startButtonPressedCallback(const std_msgs::msg::Empty::SharedPtr msg) { m_enabled = true; setVolume(ENABLED_VOLUME); @@ -141,7 +153,7 @@ void Connect4Widget::startButtonPressedCallback(const std_msgs::EmptyConstPtr& m m_desireSet->addDesire(); } -void Connect4Widget::stopButtonPressedCallback(const std_msgs::EmptyConstPtr& msg) +void Connect4Widget::stopButtonPressedCallback(const std_msgs::msg::Empty::SharedPtr msg) { m_enabled = false; setVolume(DISABLED_VOLUME); @@ -152,11 +164,11 @@ void Connect4Widget::stopButtonPressedCallback(const std_msgs::EmptyConstPtr& ms invokeLater([this]() { m_imageDisplay->setImage(QImage()); }); } -void Connect4Widget::remoteImageCallback(const opentera_webrtc_ros_msgs::PeerImageConstPtr& msg) +void Connect4Widget::remoteImageCallback(const opentera_webrtc_ros_msgs::msg::PeerImage::SharedPtr msg) { if (msg->frame.encoding != "bgr8") { - ROS_ERROR("Not support image encoding (Connect4Widget::remoteImageCallback)."); + RCLCPP_ERROR(m_node->get_logger(), "Not support image encoding (Connect4Widget::remoteImageCallback)."); return; } @@ -173,12 +185,12 @@ void Connect4Widget::remoteImageCallback(const opentera_webrtc_ros_msgs::PeerIma void Connect4Widget::setVolume(float volume) { - std_msgs::Float32 msg; + std_msgs::msg::Float32 msg; msg.data = volume; - m_volumePub.publish(msg); + m_volumePub->publish(msg); } -void Connect4Widget::openteraEventCallback(const opentera_webrtc_ros_msgs::OpenTeraEventConstPtr& msg) +void Connect4Widget::openteraEventCallback(const opentera_webrtc_ros_msgs::msg::OpenTeraEvent::SharedPtr msg) { if (!msg->join_session_events.empty()) { @@ -194,7 +206,7 @@ void Connect4Widget::openteraEventCallback(const opentera_webrtc_ros_msgs::OpenT parseSessionUrl(sessionUrl, m_connect4ManagerWebSocketUrl, m_connect4ManagerWebSocketPassword); m_observedParticipantName = getParticipantName(deviceName, sessionParameters); - ROS_INFO_STREAM("Connect4 Manager Web Socket: Connection (sessionUrl=" << sessionUrl << + RCLCPP_INFO_STREAM(m_node->get_logger(), "Connect4 Manager Web Socket: Connection (sessionUrl=" << sessionUrl << ", webSocketUrl=" << m_connect4ManagerWebSocketUrl.toStdString() << ", password=" << m_connect4ManagerWebSocketPassword.toStdString() << ", deviceName=" << deviceName << @@ -242,7 +254,8 @@ QString Connect4Widget::getParticipantName(const std::string& deviceName, const if (jsonParseError.error != QJsonParseError::NoError) { - ROS_ERROR_STREAM("Connect4 Game Data Channel: getParticipantName error: " << jsonParseError.errorString().toStdString()); + RCLCPP_ERROR_STREAM(m_node->get_logger(), "Connect4 Game Data Channel: getParticipantName error: " << + jsonParseError.errorString().toStdString()); return ""; } @@ -251,7 +264,7 @@ QString Connect4Widget::getParticipantName(const std::string& deviceName, const QString participant2 = jsonObject["participant2"].toString(); QString robot1 = jsonObject["robot1"].toString(); QString robot2 = jsonObject["robot2"].toString(); - + QString qDeviceName(deviceName.c_str()); if (qDeviceName == robot1) { @@ -263,7 +276,7 @@ QString Connect4Widget::getParticipantName(const std::string& deviceName, const } else { - ROS_ERROR("Connect4 Game Data Channel: Device name not found"); + RCLCPP_ERROR(m_node->get_logger(), "Connect4 Game Data Channel: Device name not found"); return ""; } } @@ -307,14 +320,14 @@ void Connect4Widget::addRotatingSinDesire(uint8_t r, uint8_t g, uint8_t b) constexpr double SPEED = 2.0; constexpr double DURATION_S = 4.0; - daemon_ros_client::LedColor c; + daemon_ros_client::msg::LedColor c; c.red = r; c.green = g; c.blue = b; m_desireSet->addDesire( "rotating_sin", - std::vector{c}, + std::vector{c}, SPEED, DURATION_S); } diff --git a/ros/demos/connect4/src/Connect4Widget.h b/ros/demos/connect4/src/Connect4Widget.h index 4ca71ec1..35be5d01 100644 --- a/ros/demos/connect4/src/Connect4Widget.h +++ b/ros/demos/connect4/src/Connect4Widget.h @@ -8,11 +8,12 @@ #include #include -#include +#include #include -#include -#include -#include +#include +#include +#include +#include #include #include @@ -21,19 +22,21 @@ class Connect4Widget : public QWidget { Q_OBJECT - ros::NodeHandle& m_nodeHandle; + rclcpp::Node::SharedPtr m_node; std::shared_ptr m_desireSet; std::atomic_bool m_enabled; - ros::Subscriber m_startButtonPressedSub; - ros::Subscriber m_stopButtonPressedSub; - ros::Subscriber m_remoteImageSub; + rclcpp::Subscription::SharedPtr m_startButtonPressedSub; + rclcpp::Subscription::SharedPtr m_stopButtonPressedSub; + rclcpp::Subscription::SharedPtr m_remoteImageSub; + rclcpp::Subscription::SharedPtr m_openteraEventSubscriber; + + rclcpp::Publisher::SharedPtr m_volumePub; - ros::Publisher m_volumePub; QTimer* m_setVolumeTimer; - ros::Subscriber m_openteraEventSubscriber; + QString m_connect4ManagerWebSocketUrl; QString m_connect4ManagerWebSocketPassword; QString m_observedParticipantName; @@ -43,7 +46,7 @@ class Connect4Widget : public QWidget QWebSocket* m_connect4ManagerWebSocket; public: - Connect4Widget(ros::NodeHandle& nodeHandle, std::shared_ptr desireSet, QWidget* parent = nullptr); + Connect4Widget(rclcpp::Node::SharedPtr node, std::shared_ptr desireSet, QWidget* parent = nullptr); private Q_SLOTS: void onSetVolumeTimerTimeout(); @@ -57,13 +60,13 @@ private Q_SLOTS: void onConnect4ManagerWebSocketTextMessageReceived(const QString& message); private: - void startButtonPressedCallback(const std_msgs::EmptyConstPtr& msg); - void stopButtonPressedCallback(const std_msgs::EmptyConstPtr& msg); - void remoteImageCallback(const opentera_webrtc_ros_msgs::PeerImageConstPtr& msg); + void startButtonPressedCallback(const std_msgs::msg::Empty::SharedPtr msg); + void stopButtonPressedCallback(const std_msgs::msg::Empty::SharedPtr msg); + void remoteImageCallback(const opentera_webrtc_ros_msgs::msg::PeerImage::SharedPtr msg); void setVolume(float volume); - void openteraEventCallback(const opentera_webrtc_ros_msgs::OpenTeraEventConstPtr& msg); + void openteraEventCallback(const opentera_webrtc_ros_msgs::msg::OpenTeraEvent::SharedPtr msg); bool sendConnect4ManagerEvent(const QString& event, const QJsonObject& data); QString getParticipantName(const std::string& deviceName, const std::string& sessionParameters); diff --git a/ros/demos/connect4/src/connect4_node.cpp b/ros/demos/connect4/src/connect4_node.cpp index 571058a1..63c8eee5 100644 --- a/ros/demos/connect4/src/connect4_node.cpp +++ b/ros/demos/connect4/src/connect4_node.cpp @@ -2,7 +2,7 @@ #include -#include +#include #include #include @@ -15,23 +15,21 @@ using namespace std; constexpr bool WAIT_FOR_SERVICE = true; +constexpr const char* NODE_NAME = "connnect4_node"; int startNode(int argc, char* argv[]) { - ros::init(argc, argv, "control_panel_node"); - ros::NodeHandle nodeHandle; - ros::NodeHandle privateNodeHandle("~"); + auto node = rclcpp::Node::make_shared(NODE_NAME); - bool fullscreen = false; - privateNodeHandle.param("fullscreen", fullscreen, false); + bool fullscreen = node->declare_parameter("fullscreen", false); auto desireSet = make_shared(); - auto filterPool = make_shared(nodeHandle, WAIT_FOR_SERVICE); + auto filterPool = make_shared(node, WAIT_FOR_SERVICE); vector> strategies; strategies.emplace_back(createTelepresenceStrategy(filterPool)); strategies.emplace_back(createNearestFaceFollowingStrategy(filterPool)); - strategies.emplace_back(createLedAnimationStrategy(filterPool, desireSet, nodeHandle)); + strategies.emplace_back(createLedAnimationStrategy(filterPool, desireSet, node)); strategies.emplace_back(createCamera3dRecordingStrategy(filterPool)); @@ -40,7 +38,7 @@ int startNode(int argc, char* argv[]) HbbaLite hbba(desireSet, move(strategies), {{"sound", 1}}, move(solver)); QApplication application(argc, argv); - Connect4Widget connect4Widget(nodeHandle, desireSet); + Connect4Widget connect4Widget(node, desireSet); if (fullscreen) { connect4Widget.setWindowState(Qt::WindowFullScreen); @@ -51,26 +49,33 @@ int startNode(int argc, char* argv[]) } connect4Widget.show(); - ros::AsyncSpinner spinner(1); - spinner.start(); + // Run ROS in background + rclcpp::executors::SingleThreadedExecutor rosExecutor; + rosExecutor.add_node(node); + std::thread spinThread([&rosExecutor]() { rosExecutor.spin(); }); desireSet->addDesire(); int returnCode = application.exec(); - spinner.stop(); + rosExecutor.cancel(); + spinThread.join(); return returnCode; } int main(int argc, char* argv[]) { + rclcpp::init(argc, argv); + try { return startNode(argc, argv); } catch (const std::exception& e) { - ROS_ERROR_STREAM("Control panel crashed (" << e.what() << ")"); + RCLCPP_ERROR_STREAM(rclcpp::get_logger(NODE_NAME), "Control panel crashed (" << e.what() << ")"); return -1; } + + rclcpp::shutdown(); } diff --git a/ros/demos/control_panel/CMakeLists.txt b/ros/demos/control_panel/CMakeLists.txt index c33627c7..56897513 100644 --- a/ros/demos/control_panel/CMakeLists.txt +++ b/ros/demos/control_panel/CMakeLists.txt @@ -1,153 +1,32 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(control_panel) -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - audio_analyzer - audio_utils - gesture - person_identification - roscpp - std_msgs - sensor_msgs - talk - video_analyzer - hbba_lite - t_top_hbba_lite - speech_to_text - led_animations - daemon_ros_client -) - -## System dependencies are found with CMake's conventions - -set(control_panel_components Core Widgets Gui OpenGL WebKitWidgets) -find_package(Qt5 COMPONENTS ${control_panel_components} REQUIRED) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() -## Generate messages in the 'msg' folder -# add_message_files( -# FILES -# Message1.msg -# Message2.msg -# ) +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclcpp REQUIRED) +find_package(perception_msgs REQUIRED) +find_package(t_top_hbba_lite REQUIRED) +find_package(rosidl_typesupport_cpp REQUIRED) -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -# generate_messages( -# DEPENDENCIES -# std_msgs -# ) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( - # INCLUDE_DIRS include - # LIBRARIES control_panel - # CATKIN_DEPENDS audio_analyzer gesture person_identification roscpp std_msgs talk video_analyzer - # DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( - include - ${catkin_INCLUDE_DIRS} -) - -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/control_panel.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -# add_executable(${PROJECT_NAME}_node src/control_panel_node.cpp) +set(control_panel_components Core Widgets Gui OpenGL WebKitWidgets) +find_package(Qt5 COMPONENTS ${control_panel_components} REQUIRED) +# C++ Nodes set(moc_headers src/widgets/ImageDisplay.h src/widgets/ControlPanel.h @@ -179,74 +58,14 @@ qt5_wrap_cpp(project_moc_srcs ${moc_headers}) add_executable(${PROJECT_NAME}_node ${srcs} ${uis} ${moc_headers} ${other_headers} ${project_moc_uis} ${project_moc_srcs}) qt5_use_modules(${PROJECT_NAME}_node ${control_panel_components}) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -target_link_libraries(${PROJECT_NAME}_node - ${catkin_LIBRARIES} - ${control_panel_components_link} +ament_target_dependencies(${PROJECT_NAME}_node + rclcpp + t_top_hbba_lite + perception_msgs ) +install(TARGETS ${PROJECT_NAME}_node DESTINATION lib/${PROJECT_NAME}) -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -# catkin_install_python(PROGRAMS -# scripts/my_python_script -# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_control_panel.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() +# Launch files +install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}) -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/demos/control_panel/launch/control_panel.launch b/ros/demos/control_panel/launch/control_panel.launch.xml similarity index 51% rename from ros/demos/control_panel/launch/control_panel.launch rename to ros/demos/control_panel/launch/control_panel.launch.xml index 9b98984d..a8e0c165 100644 --- a/ros/demos/control_panel/launch/control_panel.launch +++ b/ros/demos/control_panel/launch/control_panel.launch.xml @@ -2,13 +2,13 @@ - - + + - - - + + + diff --git a/ros/demos/control_panel/package.xml b/ros/demos/control_panel/package.xml index 1079ce60..014f4f46 100644 --- a/ros/demos/control_panel/package.xml +++ b/ros/demos/control_panel/package.xml @@ -1,101 +1,26 @@ - + + control_panel 0.0.0 The control_panel package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rclcpp + audio_utils_msgs + t_top_hbba_lite + perception_msgs - - - - TODO + rosidl_default_runtime + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - audio_analyzer - audio_utils - gesture - person_identification - roscpp - std_msgs - talk - video_analyzer - sensor_msgs - hbba_lite - t_top_hbba_lite - speech_to_text - led_animations - daemon_ros_client - audio_analyzer - audio_utils - gesture - person_identification - roscpp - std_msgs - talk - video_analyzer - sensor_msgs - hbba_lite - t_top_hbba_lite - speech_to_text - led_animations - daemon_ros_client - audio_analyzer - audio_utils - gesture - person_identification - roscpp - std_msgs - talk - video_analyzer - sensor_msgs - hbba_lite - t_top_hbba_lite - speech_to_text - led_animations - daemon_ros_client - - - - - + ament_cmake diff --git a/ros/demos/control_panel/src/control_panel_node.cpp b/ros/demos/control_panel/src/control_panel_node.cpp index 957d5e4b..e0f61ebd 100644 --- a/ros/demos/control_panel/src/control_panel_node.cpp +++ b/ros/demos/control_panel/src/control_panel_node.cpp @@ -2,7 +2,7 @@ #include -#include +#include #include #include @@ -17,19 +17,17 @@ using namespace std; constexpr bool WAIT_FOR_SERVICE = true; +constexpr const char* NODE_NAME = "control_panel_node"; int startNode(int argc, char* argv[]) { - ros::init(argc, argv, "control_panel_node"); - ros::NodeHandle nodeHandle; - ros::NodeHandle privateNodeHandle("~"); + auto node = rclcpp::Node::make_shared(NODE_NAME); - bool camera2dWideEnabled = false; - privateNodeHandle.param("camera_2d_wide_enabled", camera2dWideEnabled, false); + bool camera2dWideEnabled = node->declare_parameter("camera_2d_wide_enabled", false); auto desireSet = make_shared(); - auto rosFilterPool = make_unique(nodeHandle, WAIT_FOR_SERVICE); - auto filterPool = make_shared(move(rosFilterPool)); + auto rosFilterPool = make_unique(node, WAIT_FOR_SERVICE); + auto filterPool = make_shared(node, move(rosFilterPool)); vector> strategies; strategies.emplace_back(createRobotNameDetectorStrategy(filterPool)); @@ -37,17 +35,16 @@ int startNode(int argc, char* argv[]) strategies.emplace_back(createAudioAnalyzerStrategy(filterPool)); strategies.emplace_back(createVadStrategy(filterPool)); strategies.emplace_back(createSpeechToTextStrategy(filterPool)); - strategies.emplace_back(createExploreStrategy(filterPool)); - strategies.emplace_back(createFaceAnimationStrategy(filterPool, nodeHandle)); - strategies.emplace_back(createLedEmotionStrategy(filterPool, nodeHandle)); - strategies.emplace_back(createLedAnimationStrategy(filterPool, desireSet, nodeHandle)); + strategies.emplace_back(createFaceAnimationStrategy(filterPool, node)); + strategies.emplace_back(createLedEmotionStrategy(filterPool, node)); + strategies.emplace_back(createLedAnimationStrategy(filterPool, desireSet, node)); strategies.emplace_back(createSoundFollowingStrategy(filterPool)); strategies.emplace_back(createNearestFaceFollowingStrategy(filterPool)); - strategies.emplace_back(createSpecificFaceFollowingStrategy(filterPool, nodeHandle)); + strategies.emplace_back(createSpecificFaceFollowingStrategy(filterPool, node)); strategies.emplace_back(createSoundObjectPersonFollowingStrategy(filterPool)); - strategies.emplace_back(createTalkStrategy(filterPool, desireSet, nodeHandle)); - strategies.emplace_back(createGestureStrategy(filterPool, desireSet, nodeHandle)); + strategies.emplace_back(createTalkStrategy(filterPool, desireSet, node)); + strategies.emplace_back(createGestureStrategy(filterPool, desireSet, node)); strategies.emplace_back(createDanceStrategy(filterPool)); strategies.emplace_back(createTooCloseReactionStrategy(filterPool)); @@ -57,31 +54,40 @@ int startNode(int argc, char* argv[]) } auto solver = make_unique(); - auto strategyStateLogger = make_unique(); + auto strategyStateLogger = make_unique(node); HbbaLite hbba(desireSet, move(strategies), {{"sound", 1}}, move(solver), move(strategyStateLogger)); QApplication application(argc, argv); - ControlPanel controlPanel(nodeHandle, desireSet, camera2dWideEnabled); + ControlPanel controlPanel(node, desireSet, camera2dWideEnabled); // controlPanel.setFixedSize(600, 900); controlPanel.show(); - ros::AsyncSpinner spinner(1); - spinner.start(); + // Run ROS in background + rclcpp::executors::SingleThreadedExecutor rosExecutor; + rosExecutor.add_node(node); + std::thread spinThread([&rosExecutor]() { rosExecutor.spin(); }); + int returnCode = application.exec(); - spinner.stop(); + + rosExecutor.cancel(); + spinThread.join(); return returnCode; } int main(int argc, char* argv[]) { + rclcpp::init(argc, argv); + try { return startNode(argc, argv); } catch (const std::exception& e) { - ROS_ERROR_STREAM("Control panel crashed (" << e.what() << ")"); + RCLCPP_ERROR_STREAM(rclcpp::get_logger(NODE_NAME), "Control panel crashed (" << e.what() << ")"); return -1; } + + rclcpp::shutdown(); } diff --git a/ros/demos/control_panel/src/widgets/ControlPanel.cpp b/ros/demos/control_panel/src/widgets/ControlPanel.cpp index 1bd8ca1a..0191387e 100644 --- a/ros/demos/control_panel/src/widgets/ControlPanel.cpp +++ b/ros/demos/control_panel/src/widgets/ControlPanel.cpp @@ -5,8 +5,6 @@ #include #include -#include - using namespace std; constexpr int AUDIO_POWER_AMPLIFIER_MIN_VOLUME = 0; @@ -14,30 +12,32 @@ constexpr int AUDIO_POWER_AMPLIFIER_MAX_VOLUME = 63; constexpr int AUDIO_POWER_AMPLIFIER_DEFAULT_VOLUME = 24; ControlPanel::ControlPanel( - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, shared_ptr desireSet, bool camera2dWideEnabled, QWidget* parent) : QWidget(parent), - m_nodeHandle(nodeHandle), + m_node(std::move(node)), m_desireSet(std::move(desireSet)) { - m_volumePublisher = nodeHandle.advertise("daemon/set_volume", 1); + m_volumePublisher = m_node->create_publisher("daemon/set_volume", 1); createUi(camera2dWideEnabled); - m_baseStatusSubscriber = - nodeHandle.subscribe("daemon/base_status", 1, &ControlPanel::baseStatusSubscriberCallback, this); + m_baseStatusSubscriber = m_node->create_subscription( + "daemon/base_status", + 1, + [this](const daemon_ros_client::msg::BaseStatus::SharedPtr msg) { baseStatusSubscriberCallback(msg); }); } void ControlPanel::onVolumeChanged(int volume) { - std_msgs::UInt8 msg; + std_msgs::msg::UInt8 msg; msg.data = volume; - m_volumePublisher.publish(msg); + m_volumePublisher->publish(msg); } -void ControlPanel::baseStatusSubscriberCallback(const daemon_ros_client::BaseStatus::ConstPtr& msg) +void ControlPanel::baseStatusSubscriberCallback(const daemon_ros_client::msg::BaseStatus::SharedPtr msg) { int stateOfCharge = static_cast(msg->state_of_charge); int volume = msg->volume; @@ -59,11 +59,11 @@ void ControlPanel::createUi(bool camera2dWideEnabled) setWindowTitle("Control Panel"); m_avatarTab = new AvatarTab(m_desireSet); - m_speechTab = new SpeechTab(m_nodeHandle, m_desireSet); - m_gestureTab = new GestureTab(m_nodeHandle, m_desireSet); + m_speechTab = new SpeechTab(m_node, m_desireSet); + m_gestureTab = new GestureTab(m_desireSet); m_behaviorsTab = new BehaviorsTab(m_desireSet, camera2dWideEnabled); - m_ledTab = new LedTab(m_nodeHandle, m_desireSet); - m_perceptionsTab = new PerceptionsTab(m_nodeHandle, m_desireSet, camera2dWideEnabled); + m_ledTab = new LedTab(m_desireSet); + m_perceptionsTab = new PerceptionsTab(m_node, m_desireSet, camera2dWideEnabled); m_tabWidget = new QTabWidget; m_tabWidget->addTab(m_avatarTab, "Avatar"); diff --git a/ros/demos/control_panel/src/widgets/ControlPanel.h b/ros/demos/control_panel/src/widgets/ControlPanel.h index 4be7b2cd..06997e11 100644 --- a/ros/demos/control_panel/src/widgets/ControlPanel.h +++ b/ros/demos/control_panel/src/widgets/ControlPanel.h @@ -12,9 +12,11 @@ #include #include -#include -#include -#include +#include + +#include + +#include #include @@ -25,15 +27,16 @@ class ControlPanel : public QWidget { Q_OBJECT - ros::NodeHandle& m_nodeHandle; - ros::Publisher m_volumePublisher; - ros::Subscriber m_baseStatusSubscriber; + rclcpp::Node::SharedPtr m_node; + + rclcpp::Publisher::SharedPtr m_volumePublisher; + rclcpp::Subscription::SharedPtr m_baseStatusSubscriber; std::shared_ptr m_desireSet; public: ControlPanel( - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, std::shared_ptr desireSet, bool camera2dWideEnabled, QWidget* parent = nullptr); @@ -42,7 +45,7 @@ private slots: void onVolumeChanged(int volume); private: - void baseStatusSubscriberCallback(const daemon_ros_client::BaseStatus::ConstPtr& msg); + void baseStatusSubscriberCallback(const daemon_ros_client::msg::BaseStatus::SharedPtr msg); void createUi(bool camera2dWideEnabled); diff --git a/ros/demos/control_panel/src/widgets/GestureTab.cpp b/ros/demos/control_panel/src/widgets/GestureTab.cpp index 7298ed52..1615ec68 100644 --- a/ros/demos/control_panel/src/widgets/GestureTab.cpp +++ b/ros/demos/control_panel/src/widgets/GestureTab.cpp @@ -7,9 +7,8 @@ using namespace std; -GestureTab::GestureTab(ros::NodeHandle& nodeHandle, shared_ptr desireSet, QWidget* parent) +GestureTab::GestureTab(shared_ptr desireSet, QWidget* parent) : QWidget(parent), - m_nodeHandle(nodeHandle), m_desireSet(std::move(desireSet)) { createUi(); @@ -50,7 +49,10 @@ void GestureTab::setEnabledAllButtons(bool enabled) m_maybeButton->setEnabled(enabled); m_originAllButton->setEnabled(enabled); m_originHeadButton->setEnabled(enabled); + m_slowOriginHeadButton->setEnabled(enabled); m_originTorsoButton->setEnabled(enabled); + m_thinkingButton->setEnabled(enabled); + m_sadButton->setEnabled(enabled); } void GestureTab::createUi() @@ -70,16 +72,28 @@ void GestureTab::createUi() m_originHeadButton = new QPushButton("Origin Head"); connect(m_originHeadButton, &QPushButton::clicked, this, [this]() { onGestureButtonClicked("origin_head"); }); + m_slowOriginHeadButton = new QPushButton("Slow Origin Head"); + connect(m_slowOriginHeadButton, &QPushButton::clicked, this, [this]() { onGestureButtonClicked("slow_origin_head"); }); + m_originTorsoButton = new QPushButton("Origin Torso"); connect(m_originTorsoButton, &QPushButton::clicked, this, [this]() { onGestureButtonClicked("origin_torso"); }); + m_thinkingButton = new QPushButton("Thinking"); + connect(m_thinkingButton, &QPushButton::clicked, this, [this]() { onGestureButtonClicked("thinking"); }); + + m_sadButton = new QPushButton("Sad"); + connect(m_sadButton, &QPushButton::clicked, this, [this]() { onGestureButtonClicked("sad"); }); + auto globalLayout = new QVBoxLayout; globalLayout->addWidget(m_yesButton); globalLayout->addWidget(m_noButton); globalLayout->addWidget(m_maybeButton); globalLayout->addWidget(m_originAllButton); globalLayout->addWidget(m_originHeadButton); + globalLayout->addWidget(m_slowOriginHeadButton); globalLayout->addWidget(m_originTorsoButton); + globalLayout->addWidget(m_thinkingButton); + globalLayout->addWidget(m_sadButton); globalLayout->addStretch(); setLayout(globalLayout); diff --git a/ros/demos/control_panel/src/widgets/GestureTab.h b/ros/demos/control_panel/src/widgets/GestureTab.h index d01f92e2..9dfc3f22 100644 --- a/ros/demos/control_panel/src/widgets/GestureTab.h +++ b/ros/demos/control_panel/src/widgets/GestureTab.h @@ -5,9 +5,6 @@ #include #include -#include -#include - #include #include @@ -17,13 +14,11 @@ class GestureTab : public QWidget, public DesireSetObserver { Q_OBJECT - ros::NodeHandle& m_nodeHandle; - std::shared_ptr m_desireSet; QVariant m_gestureDesireId; public: - GestureTab(ros::NodeHandle& nodeHandle, std::shared_ptr desireSet, QWidget* parent = nullptr); + GestureTab(std::shared_ptr desireSet, QWidget* parent = nullptr); ~GestureTab() override; void onDesireSetChanged(const std::vector>& _) override; @@ -42,7 +37,10 @@ private slots: QPushButton* m_maybeButton; QPushButton* m_originAllButton; QPushButton* m_originHeadButton; + QPushButton* m_slowOriginHeadButton; QPushButton* m_originTorsoButton; + QPushButton* m_thinkingButton; + QPushButton* m_sadButton; }; #endif diff --git a/ros/demos/control_panel/src/widgets/LedTab.cpp b/ros/demos/control_panel/src/widgets/LedTab.cpp index 506f0ae7..4aab28cb 100644 --- a/ros/demos/control_panel/src/widgets/LedTab.cpp +++ b/ros/demos/control_panel/src/widgets/LedTab.cpp @@ -9,9 +9,9 @@ using namespace std; -daemon_ros_client::LedColor color(uint8_t r, uint8_t g, uint8_t b) +daemon_ros_client::msg::LedColor color(uint8_t r, uint8_t g, uint8_t b) { - daemon_ros_client::LedColor c; + daemon_ros_client::msg::LedColor c; c.red = r; c.green = g; c.blue = b; @@ -19,10 +19,7 @@ daemon_ros_client::LedColor color(uint8_t r, uint8_t g, uint8_t b) } -LedTab::LedTab(ros::NodeHandle& nodeHandle, shared_ptr desireSet, QWidget* parent) - : QWidget(parent), - m_nodeHandle(nodeHandle), - m_desireSet(std::move(desireSet)) +LedTab::LedTab(shared_ptr desireSet, QWidget* parent) : QWidget(parent), m_desireSet(std::move(desireSet)) { createUi(); } @@ -54,7 +51,7 @@ void LedTab::onConstantAnimationButtonToggled(bool checked) uncheckOtherAnimationButtons(m_constantAnimationButton); auto desire = - make_unique("constant", vector{color(255, 255, 255)}); + make_unique("constant", vector{color(255, 255, 255)}); m_ledAnimationDesireId = static_cast(desire->id()); m_desireSet->addDesire(std::move(desire)); } @@ -72,7 +69,7 @@ void LedTab::onRotatingSinAnimationButtonToggled(bool checked) uncheckOtherAnimationButtons(m_rotatingSinAnimationButton); auto desire = - make_unique("rotating_sin", vector{color(0, 255, 0)}); + make_unique("rotating_sin", vector{color(0, 255, 0)}); m_ledAnimationDesireId = static_cast(desire->id()); m_desireSet->addDesire(std::move(desire)); } diff --git a/ros/demos/control_panel/src/widgets/LedTab.h b/ros/demos/control_panel/src/widgets/LedTab.h index 45481968..8bfa0ecd 100644 --- a/ros/demos/control_panel/src/widgets/LedTab.h +++ b/ros/demos/control_panel/src/widgets/LedTab.h @@ -5,8 +5,6 @@ #include #include -#include - #include #include @@ -16,14 +14,12 @@ class LedTab : public QWidget { Q_OBJECT - ros::NodeHandle& m_nodeHandle; - std::shared_ptr m_desireSet; QVariant m_ledEmotionDesireId; QVariant m_ledAnimationDesireId; public: - LedTab(ros::NodeHandle& nodeHandle, std::shared_ptr desireSet, QWidget* parent = nullptr); + LedTab(std::shared_ptr desireSet, QWidget* parent = nullptr); ~LedTab() override; private slots: diff --git a/ros/demos/control_panel/src/widgets/PerceptionsTab.cpp b/ros/demos/control_panel/src/widgets/PerceptionsTab.cpp index 591102c1..0c0d64b2 100644 --- a/ros/demos/control_panel/src/widgets/PerceptionsTab.cpp +++ b/ros/demos/control_panel/src/widgets/PerceptionsTab.cpp @@ -53,13 +53,15 @@ vector getSemanticSegmentationPaletteFromClassCount(size_t classCount) return palette; } -QImage semanticSegmentationToImage(const video_analyzer::SemanticSegmentation& semanticSegmentation) +QImage semanticSegmentationToImage( + rclcpp::Node& node, + const perception_msgs::msg::SemanticSegmentation& semanticSegmentation) { int width = semanticSegmentation.width; int height = semanticSegmentation.height; if (semanticSegmentation.class_indexes.size() != width * height) { - ROS_ERROR("Invalid semantic segmentation (class_indexes.size() != width * height)"); + RCLCPP_ERROR(node.get_logger(), "Invalid semantic segmentation (class_indexes.size() != width * height)"); return QImage(); } @@ -83,39 +85,46 @@ QImage semanticSegmentationToImage(const video_analyzer::SemanticSegmentation& s } PerceptionsTab::PerceptionsTab( - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, shared_ptr desireSet, bool camera2dWideEnabled, QWidget* parent) : QWidget(parent), - m_nodeHandle(nodeHandle), + m_node(std::move(node)), m_desireSet(std::move(desireSet)), m_camera2dWideEnabled(camera2dWideEnabled) { createUi(); - m_analyzedImage3dSubscriber = - nodeHandle.subscribe("camera_3d/analysed_image", 1, &PerceptionsTab::analyzedImage3dSubscriberCallback, this); + m_analyzedImage3dSubscriber = m_node->create_subscription( + "camera_3d/analysed_image", + 1, + [this](const sensor_msgs::msg::Image::SharedPtr msg) { analyzedImage3dSubscriberCallback(msg); }); if (m_camera2dWideEnabled) { - m_analyzedImage2dWideSubscriber = nodeHandle.subscribe( + m_analyzedImage2dWideSubscriber = m_node->create_subscription( "camera_2d_wide/analysed_image", 1, - &PerceptionsTab::analyzedImage2dWideSubscriberCallback, - this); - m_videoAnalysis2dWideSubscriber = nodeHandle.subscribe( + [this](const sensor_msgs::msg::Image::SharedPtr msg) { analyzedImage2dWideSubscriberCallback(msg); }); + m_videoAnalysis2dWideSubscriber = m_node->create_subscription( "camera_2d_wide/video_analysis", 1, - &PerceptionsTab::videoAnalysis2dWideSubscriberCallback, - this); + [this](const perception_msgs::msg::VideoAnalysis::SharedPtr msg) + { videoAnalysis2dWideSubscriberCallback(msg); }); } - m_audioAnalysisSubscriber = - nodeHandle.subscribe("audio_analysis", 1, &PerceptionsTab::audioAnalysisSubscriberCallback, this); - m_robotNameDetectedSubscriber = - nodeHandle.subscribe("robot_name_detected", 1, &PerceptionsTab::robotNameDetectedSubscriberCallback, this); - m_personNamesSubscriber = - nodeHandle.subscribe("person_names", 1, &PerceptionsTab::personNamesSubscriberCallback, this); + m_audioAnalysisSubscriber = m_node->create_subscription( + "audio_analysis", + 1, + [this](const perception_msgs::msg::AudioAnalysis::SharedPtr msg) { audioAnalysisSubscriberCallback(msg); }); + m_robotNameDetectedSubscriber = m_node->create_subscription( + "robot_name_detected", + 1, + [this](const std_msgs::msg::Empty::SharedPtr msg) { robotNameDetectedSubscriberCallback(msg); }); + m_personNamesSubscriber = m_node->create_subscription( + "person_names", + 1, + [this](const perception_msgs::msg::PersonNames::SharedPtr msg) { personNamesSubscriberCallback(msg); }); } void PerceptionsTab::onVideoAnalyzer3dButtonToggled(bool checked) @@ -138,7 +147,7 @@ void PerceptionsTab::onRobotNameDetectorButtonToggled(bool checked) toggleDesire(checked, m_robotNameDetectorDesireId); } -void PerceptionsTab::analyzedImage3dSubscriberCallback(const sensor_msgs::Image::ConstPtr& msg) +void PerceptionsTab::analyzedImage3dSubscriberCallback(const sensor_msgs::msg::Image::SharedPtr msg) { if (msg->encoding != "rgb8") { @@ -152,7 +161,7 @@ void PerceptionsTab::analyzedImage3dSubscriberCallback(const sensor_msgs::Image: }); } -void PerceptionsTab::analyzedImage2dWideSubscriberCallback(const sensor_msgs::Image::ConstPtr& msg) +void PerceptionsTab::analyzedImage2dWideSubscriberCallback(const sensor_msgs::msg::Image::SharedPtr msg) { if (msg->encoding != "rgb8") { @@ -167,7 +176,7 @@ void PerceptionsTab::analyzedImage2dWideSubscriberCallback(const sensor_msgs::Im }); } -void PerceptionsTab::videoAnalysis2dWideSubscriberCallback(const video_analyzer::VideoAnalysis::ConstPtr& msg) +void PerceptionsTab::videoAnalysis2dWideSubscriberCallback(const perception_msgs::msg::VideoAnalysis::SharedPtr msg) { if (msg->semantic_segmentation.empty()) { @@ -178,23 +187,23 @@ void PerceptionsTab::videoAnalysis2dWideSubscriberCallback(const video_analyzer: [this, msg]() { m_videoAnalyzer2dWideSegmentationcImageDisplay->setImage( - semanticSegmentationToImage(msg->semantic_segmentation[0])); + semanticSegmentationToImage(*m_node, msg->semantic_segmentation[0])); }); } -void PerceptionsTab::audioAnalysisSubscriberCallback(const audio_analyzer::AudioAnalysis::ConstPtr& msg) +void PerceptionsTab::audioAnalysisSubscriberCallback(const perception_msgs::msg::AudioAnalysis::SharedPtr msg) { QString classes = mergeStdStrings(msg->audio_classes); invokeLater([this, classes]() { m_soundClassesLineEdit->setText(classes); }); } -void PerceptionsTab::robotNameDetectedSubscriberCallback(const std_msgs::Empty::ConstPtr& msg) +void PerceptionsTab::robotNameDetectedSubscriberCallback(const std_msgs::msg::Empty::SharedPtr msg) { auto currentTime = QDateTime::currentDateTime(); invokeLater([this, currentTime]() { m_robotNameDetectionTimeLineEdit->setText(currentTime.toString()); }); } -void PerceptionsTab::personNamesSubscriberCallback(const person_identification::PersonNames::ConstPtr& msg) +void PerceptionsTab::personNamesSubscriberCallback(const perception_msgs::msg::PersonNames::SharedPtr msg) { vector names; names.reserve(msg->names.size()); @@ -203,7 +212,7 @@ void PerceptionsTab::personNamesSubscriberCallback(const person_identification:: msg->names.begin(), msg->names.end(), back_inserter(names), - [](const person_identification::PersonName& name) { return name.name; }); + [](const perception_msgs::msg::PersonName& name) { return name.name; }); QString mergedNames = mergeStdStrings(names); invokeLater([this, mergedNames]() { m_identifiedPersonsLineEdit->setText(mergedNames); }); diff --git a/ros/demos/control_panel/src/widgets/PerceptionsTab.h b/ros/demos/control_panel/src/widgets/PerceptionsTab.h index a3380842..4e5226ca 100644 --- a/ros/demos/control_panel/src/widgets/PerceptionsTab.h +++ b/ros/demos/control_panel/src/widgets/PerceptionsTab.h @@ -8,12 +8,13 @@ #include #include -#include -#include -#include -#include -#include -#include +#include + +#include +#include +#include +#include +#include #include @@ -24,13 +25,14 @@ class PerceptionsTab : public QWidget { Q_OBJECT - ros::NodeHandle& m_nodeHandle; - ros::Subscriber m_analyzedImage3dSubscriber; - ros::Subscriber m_analyzedImage2dWideSubscriber; - ros::Subscriber m_videoAnalysis2dWideSubscriber; - ros::Subscriber m_audioAnalysisSubscriber; - ros::Subscriber m_robotNameDetectedSubscriber; - ros::Subscriber m_personNamesSubscriber; + rclcpp::Node::SharedPtr m_node; + + rclcpp::Subscription::SharedPtr m_analyzedImage3dSubscriber; + rclcpp::Subscription::SharedPtr m_analyzedImage2dWideSubscriber; + rclcpp::Subscription::SharedPtr m_videoAnalysis2dWideSubscriber; + rclcpp::Subscription::SharedPtr m_audioAnalysisSubscriber; + rclcpp::Subscription::SharedPtr m_robotNameDetectedSubscriber; + rclcpp::Subscription::SharedPtr m_personNamesSubscriber; std::shared_ptr m_desireSet; QVariant m_videoAnalyzer3dDesireId; @@ -42,7 +44,7 @@ class PerceptionsTab : public QWidget public: PerceptionsTab( - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, std::shared_ptr desireSet, bool camera2dWideEnabled, QWidget* parent = nullptr); @@ -54,12 +56,12 @@ private slots: void onRobotNameDetectorButtonToggled(bool checked); private: - void analyzedImage3dSubscriberCallback(const sensor_msgs::Image::ConstPtr& msg); - void analyzedImage2dWideSubscriberCallback(const sensor_msgs::Image::ConstPtr& msg); - void videoAnalysis2dWideSubscriberCallback(const video_analyzer::VideoAnalysis::ConstPtr& msg); - void audioAnalysisSubscriberCallback(const audio_analyzer::AudioAnalysis::ConstPtr& msg); - void robotNameDetectedSubscriberCallback(const std_msgs::Empty::ConstPtr& msg); - void personNamesSubscriberCallback(const person_identification::PersonNames::ConstPtr& msg); + void analyzedImage3dSubscriberCallback(const sensor_msgs::msg::Image::SharedPtr msg); + void analyzedImage2dWideSubscriberCallback(const sensor_msgs::msg::Image::SharedPtr msg); + void videoAnalysis2dWideSubscriberCallback(const perception_msgs::msg::VideoAnalysis::SharedPtr msg); + void audioAnalysisSubscriberCallback(const perception_msgs::msg::AudioAnalysis::SharedPtr msg); + void robotNameDetectedSubscriberCallback(const std_msgs::msg::Empty::SharedPtr msg); + void personNamesSubscriberCallback(const perception_msgs::msg::PersonNames::SharedPtr msg); void createUi(); diff --git a/ros/demos/control_panel/src/widgets/SpeechTab.cpp b/ros/demos/control_panel/src/widgets/SpeechTab.cpp index b10356e6..9180101a 100644 --- a/ros/demos/control_panel/src/widgets/SpeechTab.cpp +++ b/ros/demos/control_panel/src/widgets/SpeechTab.cpp @@ -9,17 +9,22 @@ using namespace std; -SpeechTab::SpeechTab(ros::NodeHandle& nodeHandle, shared_ptr desireSet, QWidget* parent) +SpeechTab::SpeechTab(rclcpp::Node::SharedPtr node, shared_ptr desireSet, QWidget* parent) : QWidget(parent), - m_nodeHandle(nodeHandle), + m_node(std::move(node)), m_desireSet(std::move(desireSet)) { createUi(); m_desireSet->addObserver(this); - m_speechToTextSubscriber = - nodeHandle.subscribe("speech_to_text/transcript", 1, &SpeechTab::speechToTextSubscriberCallback, this); - m_vadSubscriber = nodeHandle.subscribe("voice_activity", 1, &SpeechTab::vadSubscriberCallback, this); + m_speechToTextSubscriber = m_node->create_subscription( + "speech_to_text/transcript", + 1, + [this](const perception_msgs::msg::Transcript::SharedPtr msg) { speechToTextSubscriberCallback(msg); }); + m_vadSubscriber = m_node->create_subscription( + "voice_activity", + 1, + [this](const audio_utils_msgs::msg::VoiceActivity::SharedPtr msg) { vadSubscriberCallback(msg); }); } SpeechTab::~SpeechTab() @@ -80,12 +85,12 @@ void SpeechTab::onVadButtonToggled(bool checked) } } -void SpeechTab::speechToTextSubscriberCallback(const speech_to_text::Transcript::ConstPtr& msg) +void SpeechTab::speechToTextSubscriberCallback(const perception_msgs::msg::Transcript::SharedPtr msg) { invokeLater([=]() { m_listenedTextTextEdit->append(QString::fromStdString(msg->text)); }); } -void SpeechTab::vadSubscriberCallback(const audio_utils::VoiceActivity::ConstPtr& msg) +void SpeechTab::vadSubscriberCallback(const audio_utils_msgs::msg::VoiceActivity::SharedPtr msg) { invokeLater( [=]() diff --git a/ros/demos/control_panel/src/widgets/SpeechTab.h b/ros/demos/control_panel/src/widgets/SpeechTab.h index a72719c2..c3e119b4 100644 --- a/ros/demos/control_panel/src/widgets/SpeechTab.h +++ b/ros/demos/control_panel/src/widgets/SpeechTab.h @@ -7,10 +7,10 @@ #include #include -#include -#include -#include -#include +#include + +#include +#include #include @@ -21,9 +21,10 @@ class SpeechTab : public QWidget, public DesireSetObserver { Q_OBJECT - ros::NodeHandle& m_nodeHandle; - ros::Subscriber m_speechToTextSubscriber; - ros::Subscriber m_vadSubscriber; + rclcpp::Node::SharedPtr m_node; + + rclcpp::Subscription::SharedPtr m_speechToTextSubscriber; + rclcpp::Subscription::SharedPtr m_vadSubscriber; std::shared_ptr m_desireSet; QVariant m_talkDesireId; @@ -31,7 +32,7 @@ class SpeechTab : public QWidget, public DesireSetObserver QVariant m_vadDesireId; public: - SpeechTab(ros::NodeHandle& nodeHandle, std::shared_ptr desireSet, QWidget* parent = nullptr); + SpeechTab(rclcpp::Node::SharedPtr node, std::shared_ptr desireSet, QWidget* parent = nullptr); ~SpeechTab() override; void onDesireSetChanged(const std::vector>& _) override; @@ -42,8 +43,8 @@ private slots: void onVadButtonToggled(bool checked); private: - void speechToTextSubscriberCallback(const speech_to_text::Transcript::ConstPtr& msg); - void vadSubscriberCallback(const audio_utils::VoiceActivity::ConstPtr& msg); + void speechToTextSubscriberCallback(const perception_msgs::msg::Transcript::SharedPtr msg); + void vadSubscriberCallback(const audio_utils_msgs::msg::VoiceActivity::SharedPtr msg); void createUi(); diff --git a/ros/demos/home_logger/CMakeLists.txt b/ros/demos/home_logger/CMakeLists.txt index 93f9e552..d3cafec3 100644 --- a/ros/demos/home_logger/CMakeLists.txt +++ b/ros/demos/home_logger/CMakeLists.txt @@ -1,148 +1,35 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(home_logger) -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - audio_analyzer - cloud_data - gesture - hbba_lite - person_identification - roscpp - rospy - sensor_msgs - speech_to_text - std_msgs - t_top_hbba_lite - talk - tf - video_analyzer - recorders - led_animations - daemon_ros_client -) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -# add_message_files( -# FILES -# Message1.msg -# Message2.msg -# ) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -# generate_messages( -# DEPENDENCIES -# sensor_msgs# std_msgs -# ) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() -if(CMAKE_BUILD_TYPE MATCHES Debug) - set(_FMT_LIB_NAME fmtd) -else() - set(_FMT_LIB_NAME fmt) +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) endif() -catkin_package( - INCLUDE_DIRS include 3rd_party/fmt/include - LIBRARIES home_logger_common ${_FMT_LIB_NAME} -# CATKIN_DEPENDS audio_analyzer cloud_data gesture hbba_lite person_identification roscpp rospy sensor_msgs speech_to_text std_msgs t_top_hbba_lite talk tf video_analyzer recorders -# DEPENDS system_lib -) +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() -unset(_FMT_LIB_NAME) +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclcpp REQUIRED) +find_package(cloud_data REQUIRED) +find_package(t_top_hbba_lite REQUIRED) +find_package(recorders REQUIRED) +find_package(tf2 REQUIRED) +find_package(perception_msgs REQUIRED) +# C++ Library add_subdirectory(3rd_party/fmt) -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations include_directories( include - ${catkin_INCLUDE_DIRS} 3rd_party/fmt/include ) @@ -164,15 +51,14 @@ add_library(home_logger_common src/home_logger_common/managers/AlarmManager.cpp src/home_logger_common/managers/ReminderManager.cpp ) +ament_target_dependencies(home_logger_common + rclcpp + t_top_hbba_lite + recorders + perception_msgs +) +target_link_libraries(home_logger_common ${recorders_LIBRARIES}) -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide add_executable(${PROJECT_NAME}_node src/home_logger_node.cpp src/managers/VolumeManager.cpp @@ -204,100 +90,53 @@ add_executable(${PROJECT_NAME}_node src/states/specific/AlarmState.cpp src/states/specific/TellReminderState.cpp ) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -target_link_libraries(home_logger_common - ${catkin_LIBRARIES} - fmt +ament_target_dependencies(${PROJECT_NAME}_node + rclcpp + cloud_data + t_top_hbba_lite + tf2 ) - target_link_libraries(${PROJECT_NAME}_node - ${catkin_LIBRARIES} home_logger_common fmt ) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -# catkin_install_python(PROGRAMS -# scripts/my_python_script -# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -catkin_add_gtest(home_logger_common-test - test/home_logger_common/main.cpp - test/home_logger_common/loadStringResources.cpp - test/home_logger_common/StringUtilsTests.cpp - test/home_logger_common/DateTimeTests.cpp - test/home_logger_common/PropertiesTests.cpp - test/home_logger_common/commands/CommandsTests.cpp - test/home_logger_common/commands/CommandParsersTests.cpp - test/home_logger_common/commands/AllCommandParserTests.cpp - test/home_logger_common/parameters/CommandParametersParserTests.cpp - test/home_logger_common/parameters/WeatherCommandParametersParserTests.cpp - test/home_logger_common/parameters/SetVolumeCommandParametersParserTests.cpp - test/home_logger_common/parameters/AlarmCommandParametersParsersTests.cpp - test/home_logger_common/parameters/ReminderCommandParametersParsersTests.cpp - test/home_logger_common/language/LanguageTests.cpp - test/home_logger_common/language/StringResourcesTests.cpp - test/home_logger_common/language/FormatterTests.cpp - test/home_logger_common/managers/AlarmManagerTests.cpp - test/home_logger_common/managers/ReminderManagerTests.cpp -) -if(TARGET home_logger_common-test) - find_package(Boost REQUIRED COMPONENTS system filesystem) - target_link_libraries(home_logger_common-test home_logger_common ${Boost_LIBRARIES} ${catkin_LIBRARIES} fmt) +install(TARGETS ${PROJECT_NAME}_node DESTINATION lib/${PROJECT_NAME}) + +# Launch files +install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}) + +# Resources files +install(DIRECTORY resources DESTINATION share/${PROJECT_NAME}) + +# Tests +if(BUILD_TESTING) + find_package(ament_cmake_gtest REQUIRED) + ament_add_gtest(${PROJECT_NAME}_test + test/home_logger_common/main.cpp + test/home_logger_common/loadStringResources.cpp + test/home_logger_common/StringUtilsTests.cpp + test/home_logger_common/DateTimeTests.cpp + test/home_logger_common/PropertiesTests.cpp + test/home_logger_common/commands/CommandsTests.cpp + test/home_logger_common/commands/CommandParsersTests.cpp + test/home_logger_common/commands/AllCommandParserTests.cpp + test/home_logger_common/parameters/CommandParametersParserTests.cpp + test/home_logger_common/parameters/WeatherCommandParametersParserTests.cpp + test/home_logger_common/parameters/SetVolumeCommandParametersParserTests.cpp + test/home_logger_common/parameters/AlarmCommandParametersParsersTests.cpp + test/home_logger_common/parameters/ReminderCommandParametersParsersTests.cpp + test/home_logger_common/language/LanguageTests.cpp + test/home_logger_common/language/StringResourcesTests.cpp + test/home_logger_common/language/FormatterTests.cpp + test/home_logger_common/managers/AlarmManagerTests.cpp + test/home_logger_common/managers/ReminderManagerTests.cpp + ) + ament_target_dependencies(${PROJECT_NAME}_test + rclcpp + t_top_hbba_lite + ) + target_link_libraries(${PROJECT_NAME}_test ${recorders_LIBRARIES} home_logger_common fmt) endif() -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) + +ament_package() diff --git a/ros/demos/home_logger/launch/home_logger.launch b/ros/demos/home_logger/launch/home_logger.launch.xml similarity index 52% rename from ros/demos/home_logger/launch/home_logger.launch rename to ros/demos/home_logger/launch/home_logger.launch.xml index 40811175..191df3be 100644 --- a/ros/demos/home_logger/launch/home_logger.launch +++ b/ros/demos/home_logger/launch/home_logger.launch.xml @@ -4,43 +4,43 @@ - - + + - - + + - - - + + + - + - + - - + + - - - + + + - + diff --git a/ros/demos/home_logger/package.xml b/ros/demos/home_logger/package.xml index 77310516..f635ca56 100644 --- a/ros/demos/home_logger/package.xml +++ b/ros/demos/home_logger/package.xml @@ -1,110 +1,28 @@ - + + home_logger 0.0.0 The home_logger package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rclcpp + cloud_data + t_top_hbba_lite + recorders + tf2 + perception_msgs - - - - TODO + rosidl_default_runtime + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - audio_analyzer - cloud_data - gesture - hbba_lite - person_identification - roscpp - rospy - sensor_msgs - speech_to_text - std_msgs - t_top_hbba_lite - talk - tf - video_analyzer - recorders - led_animations - daemon_ros_client - audio_analyzer - cloud_data - gesture - hbba_lite - person_identification - roscpp - rospy - sensor_msgs - speech_to_text - std_msgs - t_top_hbba_lite - talk - tf - video_analyzer - recorders - led_animations - daemon_ros_client - audio_analyzer - cloud_data - gesture - hbba_lite - person_identification - roscpp - rospy - sensor_msgs - speech_to_text - std_msgs - t_top_hbba_lite - talk - tf - video_analyzer - recorders - led_animations - daemon_ros_client - - - - - + ament_cmake diff --git a/ros/demos/home_logger/src/executors/AllCommandExecutor.cpp b/ros/demos/home_logger/src/executors/AllCommandExecutor.cpp index 9ac935d4..7ffd1040 100644 --- a/ros/demos/home_logger/src/executors/AllCommandExecutor.cpp +++ b/ros/demos/home_logger/src/executors/AllCommandExecutor.cpp @@ -12,14 +12,14 @@ using namespace std; AllCommandExecutor::AllCommandExecutor( StateManager& stateManager, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, VolumeManager& volumeManager, AlarmManager& alarmManager, ReminderManager& reminderManager) { vector> executors; - executors.emplace_back(make_unique(stateManager, nodeHandle)); + executors.emplace_back(make_unique(stateManager, node)); executors.emplace_back(make_unique(stateManager, volumeManager)); executors.emplace_back(make_unique(stateManager, volumeManager)); diff --git a/ros/demos/home_logger/src/executors/AllCommandExecutor.h b/ros/demos/home_logger/src/executors/AllCommandExecutor.h index 319f40b5..33abbaea 100644 --- a/ros/demos/home_logger/src/executors/AllCommandExecutor.h +++ b/ros/demos/home_logger/src/executors/AllCommandExecutor.h @@ -17,7 +17,7 @@ class AllCommandExecutor public: AllCommandExecutor( StateManager& stateManager, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, VolumeManager& volumeManager, AlarmManager& alarmManager, ReminderManager& reminderManager); diff --git a/ros/demos/home_logger/src/executors/WeatherCommandExecutor.cpp b/ros/demos/home_logger/src/executors/WeatherCommandExecutor.cpp index 7d23c87f..fec7d8bb 100644 --- a/ros/demos/home_logger/src/executors/WeatherCommandExecutor.cpp +++ b/ros/demos/home_logger/src/executors/WeatherCommandExecutor.cpp @@ -7,17 +7,25 @@ #include #include -#include -#include - #include using namespace std; -WeatherCommandExecutor::WeatherCommandExecutor(StateManager& stateManager, ros::NodeHandle& nodeHandle) +constexpr chrono::seconds WEATHER_SERVICE_TIMEOUT(20); + +WeatherCommandExecutor::WeatherCommandExecutor(StateManager& stateManager, rclcpp::Node::SharedPtr node) : SpecificCommandExecutor(stateManager), - m_nodeHandle(nodeHandle) + m_node(move(node)) { + m_weatherClientCallbackGroup = m_node->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive); + m_currentWeatherClient = m_node->create_client( + "cloud_data/current_local_weather", + rmw_qos_profile_services_default, + m_weatherClientCallbackGroup); + m_weatherForecastClient = m_node->create_client( + "cloud_data/local_weather_forecast", + rmw_qos_profile_services_default, + m_weatherClientCallbackGroup); } WeatherCommandExecutor::~WeatherCommandExecutor() {} @@ -71,95 +79,118 @@ void WeatherCommandExecutor::executeSpecific(const shared_ptr& c void WeatherCommandExecutor::getCurrentWeatherText(string& text, bool& ok) { - ros::ServiceClient service = - m_nodeHandle.serviceClient("cloud_data/current_local_weather"); + auto request = make_shared(); + auto future = m_currentWeatherClient->async_send_request(request); + + if (future.wait_for(WEATHER_SERVICE_TIMEOUT) != future_status::ready) + { + ok = false; + return; + } - cloud_data::CurrentLocalWeather srv; - ok = service.exists() && service.call(srv); - if (!ok) + auto response = future.get(); + if (!response->ok) { + ok = false; return; } + ok = true; text = Formatter::format( StringResources::getValue("dialogs.commands.weather.current"), - fmt::arg("temperature_celsius", srv.response.temperature_celsius), - fmt::arg("weather_description", srv.response.weather_description)); + fmt::arg("temperature_celsius", response->temperature_celsius), + fmt::arg("weather_description", response->weather_description)); } void WeatherCommandExecutor::getTodayWeatherForecastText(string& text, bool& ok) { - ros::ServiceClient service = - m_nodeHandle.serviceClient("cloud_data/local_weather_forecast"); + auto request = make_shared(); + request->relative_day = 0; + auto future = m_weatherForecastClient->async_send_request(request); - cloud_data::LocalWeatherForecast srv; - srv.request.relative_day = 0; - ok = service.exists() && service.call(srv); - if (!ok) + if (future.wait_for(WEATHER_SERVICE_TIMEOUT) != future_status::ready) { + ok = false; return; } + auto response = future.get(); + if (!response->ok) + { + ok = false; + return; + } + + ok = true; + stringstream ss; auto currentTime = Time::now(); if (currentTime < Time(12, 00)) { ss << Formatter::format( StringResources::getValue("dialogs.commands.weather.today.morning"), - fmt::arg("temperature_celsius", srv.response.temperature_morning_celsius)); + fmt::arg("temperature_celsius", response->temperature_morning_celsius)); ss << "\n"; } if (currentTime < Time(17, 00)) { ss << Formatter::format( StringResources::getValue("dialogs.commands.weather.today.day"), - fmt::arg("temperature_celsius", srv.response.temperature_day_celsius)); + fmt::arg("temperature_celsius", response->temperature_day_celsius)); ss << "\n"; } if (currentTime < Time(21, 00)) { ss << Formatter::format( StringResources::getValue("dialogs.commands.weather.today.evening"), - fmt::arg("temperature_celsius", srv.response.temperature_evening_celsius)); + fmt::arg("temperature_celsius", response->temperature_evening_celsius)); ss << "\n"; } ss << Formatter::format( StringResources::getValue("dialogs.commands.weather.today.night"), - fmt::arg("temperature_celsius", srv.response.temperature_night_celsius)); + fmt::arg("temperature_celsius", response->temperature_night_celsius)); text = ss.str(); } void WeatherCommandExecutor::getTomorrowWeatherForecastText(string& text, bool& ok) { - ros::ServiceClient service = - m_nodeHandle.serviceClient("cloud_data/local_weather_forecast"); + auto request = make_shared(); + request->relative_day = 1; + auto future = m_weatherForecastClient->async_send_request(request); - cloud_data::LocalWeatherForecast srv; - srv.request.relative_day = 0; - ok = service.exists() && service.call(srv); - if (!ok) + if (future.wait_for(WEATHER_SERVICE_TIMEOUT) != future_status::ready) { + ok = false; return; } + auto response = future.get(); + if (!response->ok) + { + ok = false; + return; + } + + ok = true; + stringstream ss; ss << Formatter::format( StringResources::getValue("dialogs.commands.weather.tomorrow.morning"), - fmt::arg("temperature_celsius", srv.response.temperature_morning_celsius)); + fmt::arg("temperature_celsius", response->temperature_morning_celsius)); ss << "\n"; ss << Formatter::format( StringResources::getValue("dialogs.commands.weather.tomorrow.day"), - fmt::arg("temperature_celsius", srv.response.temperature_day_celsius)); + fmt::arg("temperature_celsius", response->temperature_day_celsius)); ss << "\n"; ss << Formatter::format( StringResources::getValue("dialogs.commands.weather.tomorrow.evening"), - fmt::arg("temperature_celsius", srv.response.temperature_evening_celsius)); + fmt::arg("temperature_celsius", response->temperature_evening_celsius)); ss << "\n"; ss << Formatter::format( StringResources::getValue("dialogs.commands.weather.tomorrow.night"), - fmt::arg("temperature_celsius", srv.response.temperature_night_celsius)); + fmt::arg("temperature_celsius", response->temperature_night_celsius)); text = ss.str(); } @@ -169,21 +200,30 @@ void WeatherCommandExecutor::getWeekWeatherForecastText(string& text, bool& ok) constexpr int DAY_COUNT = 7; float temperatures[DAY_COUNT]; - ros::ServiceClient service = - m_nodeHandle.serviceClient("cloud_data/local_weather_forecast"); + auto request = make_shared(); + for (size_t i = 0; i < DAY_COUNT; i++) { - cloud_data::LocalWeatherForecast srv; - srv.request.relative_day = i; - ok = service.exists() && service.call(srv); - if (!ok) + request->relative_day = i; + auto future = m_weatherForecastClient->async_send_request(request); + if (future.wait_for(WEATHER_SERVICE_TIMEOUT) != future_status::ready) { + ok = false; return; } - temperatures[i] = srv.response.temperature_day_celsius; + auto response = future.get(); + if (!response->ok) + { + ok = false; + return; + } + + temperatures[i] = response->temperature_day_celsius; } + ok = true; + int currentWeekDay = Date::now().weekDay(); string temperatureSentence = StringResources::getValue("dialogs.commands.weather.week.temperature"); diff --git a/ros/demos/home_logger/src/executors/WeatherCommandExecutor.h b/ros/demos/home_logger/src/executors/WeatherCommandExecutor.h index 52b1e5cf..157545ba 100644 --- a/ros/demos/home_logger/src/executors/WeatherCommandExecutor.h +++ b/ros/demos/home_logger/src/executors/WeatherCommandExecutor.h @@ -3,12 +3,19 @@ #include "CommandExecutor.h" +#include +#include + class WeatherCommandExecutor : public SpecificCommandExecutor { - ros::NodeHandle& m_nodeHandle; + rclcpp::Node::SharedPtr m_node; + + rclcpp::CallbackGroup::SharedPtr m_weatherClientCallbackGroup; + rclcpp::Client::SharedPtr m_currentWeatherClient; + rclcpp::Client::SharedPtr m_weatherForecastClient; public: - WeatherCommandExecutor(StateManager& stateManager, ros::NodeHandle& nodeHandle); + WeatherCommandExecutor(StateManager& stateManager, rclcpp::Node::SharedPtr node); ~WeatherCommandExecutor() override; protected: diff --git a/ros/demos/home_logger/src/home_logger_node.cpp b/ros/demos/home_logger/src/home_logger_node.cpp index 5688363c..8cbe73a1 100644 --- a/ros/demos/home_logger/src/home_logger_node.cpp +++ b/ros/demos/home_logger/src/home_logger_node.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include @@ -28,11 +28,13 @@ #include #include +#include using namespace std; constexpr bool WAIT_FOR_SERVICE = true; -constexpr double STARTUP_DELAY_S = 30.0; +constexpr int STARTUP_DELAY_S = 30; +constexpr const char* NODE_NAME = "home_logger_node"; void loadResources(Language language, const string& englishStringResourcePath, const string& frenchStringResourcesPath) { @@ -51,7 +53,7 @@ void loadResources(Language language, const string& englishStringResourcePath, c } void startNode( - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, Language language, const string& englishStringResourcePath, const string& frenchStringResourcesPath, @@ -69,7 +71,7 @@ void startNode( Formatter::initialize(language); auto desireSet = make_shared(); - auto filterPool = make_shared(nodeHandle, WAIT_FOR_SERVICE); + auto filterPool = make_shared(node, WAIT_FOR_SERVICE); vector> strategies; if (recordSession) @@ -86,52 +88,44 @@ void startNode( strategies.emplace_back(createAudioAnalyzerStrategy(filterPool)); strategies.emplace_back(createSpeechToTextStrategy(filterPool)); - strategies.emplace_back(createFaceAnimationStrategy(filterPool, nodeHandle)); + strategies.emplace_back(createFaceAnimationStrategy(filterPool, node)); strategies.emplace_back(createNearestFaceFollowingStrategy(filterPool)); strategies.emplace_back(createSoundFollowingStrategy(filterPool)); - strategies.emplace_back(createTalkStrategy(filterPool, desireSet, nodeHandle)); - strategies.emplace_back(createGestureStrategy(filterPool, desireSet, nodeHandle)); - strategies.emplace_back(createPlaySoundStrategy(filterPool, desireSet, nodeHandle)); + strategies.emplace_back(createTalkStrategy(filterPool, desireSet, node)); + strategies.emplace_back(createGestureStrategy(filterPool, desireSet, node)); + strategies.emplace_back(createPlaySoundStrategy(filterPool, desireSet, node)); auto solver = make_unique(); - auto strategyStateLogger = make_unique(nodeHandle); + auto strategyStateLogger = make_unique(node); HbbaLite hbba(desireSet, move(strategies), {{"sound", 1}}, move(solver), move(strategyStateLogger)); - VolumeManager volumeManager(nodeHandle); + VolumeManager volumeManager(node); SQLite::Database database(databasePath, SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE); AlarmManager alarmManager(database); ReminderManager reminderManager(database); - StateManager stateManager(desireSet, nodeHandle); - stateManager.addState(make_unique(stateManager, desireSet, nodeHandle)); + StateManager stateManager(desireSet, node); + stateManager.addState(make_unique(stateManager, desireSet, node)); stateManager.addState(make_unique( stateManager, desireSet, - nodeHandle, + node, alarmManager, reminderManager, sleepTime, wakeUpTime, faceDescriptorThreshold)); - stateManager.addState(make_unique(stateManager, desireSet, nodeHandle, sleepTime, wakeUpTime)); - stateManager.addState(make_unique(stateManager, desireSet, nodeHandle)); - stateManager.addState(make_unique( - stateManager, - desireSet, - nodeHandle, - volumeManager, - alarmManager, - reminderManager)); - stateManager.addState(make_unique(stateManager, desireSet, nodeHandle)); - stateManager.addState(make_unique( - stateManager, - desireSet, - nodeHandle, - noseConfidenceThreshold)); + stateManager.addState(make_unique(stateManager, desireSet, node, sleepTime, wakeUpTime)); + stateManager.addState(make_unique(stateManager, desireSet, node)); + stateManager.addState( + make_unique(stateManager, desireSet, node, volumeManager, alarmManager, reminderManager)); + stateManager.addState(make_unique(stateManager, desireSet, node)); + stateManager.addState( + make_unique(stateManager, desireSet, node, noseConfidenceThreshold)); - stateManager.addState(make_unique(stateManager, desireSet, nodeHandle, alarmManager, alarmPath)); - stateManager.addState(make_unique(stateManager, desireSet, nodeHandle, reminderManager)); + stateManager.addState(make_unique(stateManager, desireSet, node, alarmManager, alarmPath)); + stateManager.addState(make_unique(stateManager, desireSet, node, reminderManager)); if (recordSession) @@ -151,117 +145,99 @@ void startNode( stateManager.switchTo(); - ros::spin(); + rclcpp::executors::MultiThreadedExecutor executor(rclcpp::ExecutorOptions(), 2); + executor.add_node(node); + executor.spin(); } -int startNode(int argc, char** argv) +int startNode() { - ros::init(argc, argv, "home_logger_node"); - ros::NodeHandle nodeHandle; - ros::NodeHandle privateNodeHandle("~"); + auto node = rclcpp::Node::make_shared(NODE_NAME); - string languageString; + string languageString = node->declare_parameter("language", ""); Language language; - privateNodeHandle.param("language", languageString, ""); if (!languageFromString(languageString, language)) { - ROS_ERROR("Language must be English (language=en) or French (language=fr)."); + RCLCPP_ERROR(node->get_logger(), "Language must be English (language=en) or French (language=fr)."); return -1; } - string englishStringResourcePath; - if (!privateNodeHandle.getParam("english_string_resource_path", englishStringResourcePath)) + string englishStringResourcePath = node->declare_parameter("english_string_resource_path", ""); + if (englishStringResourcePath == "") { - ROS_ERROR("The parameter english_string_resource_path must be set."); + RCLCPP_ERROR(node->get_logger(), "The parameter english_string_resource_path must be set."); return -1; } - string frenchStringResourcesPath; - if (!privateNodeHandle.getParam("french_string_resources_path", frenchStringResourcesPath)) + string frenchStringResourcesPath = node->declare_parameter("french_string_resources_path", ""); + if (frenchStringResourcesPath == "") { - ROS_ERROR("The parameter french_string_resources_path must be set."); + RCLCPP_ERROR(node->get_logger(), "The parameter french_string_resources_path must be set."); return -1; } - string databasePath; - if (!privateNodeHandle.getParam("database_path", databasePath)) + string databasePath = node->declare_parameter("database_path", ""); + if (databasePath == "") { - ROS_ERROR("The parameter database_path is required."); + RCLCPP_ERROR(node->get_logger(), "The parameter database_path is required."); return -1; } - int sleepTimeHour; - int sleepTimeMinute; - int wakeUpTimeHour; - int wakeUpTimeMinute; - if (!privateNodeHandle.getParam("sleep_time_hour", sleepTimeHour)) + int sleepTimeHour = node->declare_parameter("sleep_time_hour", -1); + int sleepTimeMinute = node->declare_parameter("sleep_time_minute", -1); + int wakeUpTimeHour = node->declare_parameter("wake_up_time_hour", -1); + int wakeUpTimeMinute = node->declare_parameter("wake_up_time_minute", -1); + if (sleepTimeHour == -1) { - ROS_ERROR("The parameter sleep_time_hour must be set."); + RCLCPP_ERROR(node->get_logger(), "The parameter sleep_time_hour must be set."); return -1; } - if (!privateNodeHandle.getParam("sleep_time_minute", sleepTimeMinute)) + if (sleepTimeMinute == -1) { - ROS_ERROR("The parameter sleep_time_minute must be set."); + RCLCPP_ERROR(node->get_logger(), "The parameter sleep_time_minute must be set."); return -1; } - if (!privateNodeHandle.getParam("wake_up_time_hour", wakeUpTimeHour)) + if (wakeUpTimeHour == -1) { - ROS_ERROR("The parameter wake_up_time_hour must be set."); + RCLCPP_ERROR(node->get_logger(), "The parameter wake_up_time_hour must be set."); return -1; } - if (!privateNodeHandle.getParam("wake_up_time_minute", wakeUpTimeMinute)) - { - ROS_ERROR("The parameter wake_up_time_minute must be set."); - return -1; - } - - string alarmPath; - if (!privateNodeHandle.getParam("alarm_path", alarmPath)) + if (wakeUpTimeMinute == -1) { - ROS_ERROR("The parameter alarm_path must be set."); + RCLCPP_ERROR(node->get_logger(), "The parameter wake_up_time_minute must be set."); return -1; } - float faceDescriptorThreshold; - if (!privateNodeHandle.getParam("face_descriptor_threshold", faceDescriptorThreshold)) + string alarmPath = node->declare_parameter("alarm_path", ""); + if (alarmPath == "") { - ROS_ERROR("The parameter face_descriptor_threshold must be set."); + RCLCPP_ERROR(node->get_logger(), "The parameter alarm_path must be set."); return -1; } - float noseConfidenceThreshold; - if (!privateNodeHandle.getParam("nose_confidence_threshold", noseConfidenceThreshold)) + float faceDescriptorThreshold = node->declare_parameter("face_descriptor_threshold", -1.f); + if (faceDescriptorThreshold == -1.f) { - ROS_ERROR("The parameter nose_confidence_threshold must be set."); + RCLCPP_ERROR(node->get_logger(), "The parameter face_descriptor_threshold must be set."); return -1; } - - bool camera2dWideEnabled; - if (!privateNodeHandle.getParam("camera_2d_wide_enabled", camera2dWideEnabled)) + float noseConfidenceThreshold = node->declare_parameter("nose_confidence_threshold", -1.f); + if (noseConfidenceThreshold == -1.f) { - ROS_ERROR("The parameter camera_2d_wide_enabled must be set."); + RCLCPP_ERROR(node->get_logger(), "The parameter nose_confidence_threshold must be set."); return -1; } - bool recordSession; - if (!privateNodeHandle.getParam("record_session", recordSession)) - { - ROS_ERROR("The parameter record_session must be set."); - return -1; - } - bool logPerceptions; - if (!privateNodeHandle.getParam("log_perceptions", logPerceptions)) - { - ROS_ERROR("The parameter log_perceptions must be set."); - return -1; - } + bool camera2dWideEnabled = node->declare_parameter("camera_2d_wide_enabled", false); + bool recordSession = node->declare_parameter("record_session", false); + bool logPerceptions = node->declare_parameter("log_perceptions", false); - ROS_INFO("Waiting nodes."); - ros::Duration(STARTUP_DELAY_S).sleep(); + RCLCPP_INFO(node->get_logger(), "Waiting nodes."); + this_thread::sleep_for(chrono::seconds(STARTUP_DELAY_S)); startNode( - nodeHandle, + node, language, englishStringResourcePath, frenchStringResourcesPath, @@ -280,13 +256,17 @@ int startNode(int argc, char** argv) int main(int argc, char** argv) { + rclcpp::init(argc, argv); + try { - return startNode(argc, argv); + return startNode(); } catch (const exception& e) { - ROS_ERROR_STREAM("Home logger crashed (" << e.what() << ")"); + RCLCPP_ERROR_STREAM(rclcpp::get_logger(NODE_NAME), "Home logger crashed (" << e.what() << ")"); return -1; } + + rclcpp::shutdown(); } diff --git a/ros/demos/home_logger/src/managers/VolumeManager.cpp b/ros/demos/home_logger/src/managers/VolumeManager.cpp index 2d11525a..b3d469d9 100644 --- a/ros/demos/home_logger/src/managers/VolumeManager.cpp +++ b/ros/demos/home_logger/src/managers/VolumeManager.cpp @@ -6,10 +6,16 @@ using namespace std; constexpr float MAXIMUM_INT_VOLUME_VALUE = 63.f; -VolumeManager::VolumeManager(ros::NodeHandle& nodeHandle) : m_currentVolumePercent(35), m_maximumVolumePercent(100.f) +VolumeManager::VolumeManager(rclcpp::Node::SharedPtr node) + : m_node(move(node)), + m_currentVolumePercent(35), + m_maximumVolumePercent(100.f) { - m_volumePublisher = nodeHandle.advertise("daemon/set_volume", 1); - m_baseStatusSubscriber = nodeHandle.subscribe("daemon/base_status", 1, &VolumeManager::baseStatusSubscriberCallback, this); + m_volumePublisher = node->create_publisher("daemon/set_volume", 1); + m_baseStatusSubscriber = node->create_subscription( + "daemon/base_status", + 1, + [this](const daemon_ros_client::msg::BaseStatus::SharedPtr msg) { baseStatusSubscriberCallback(msg); }); setVolume(m_currentVolumePercent); } @@ -21,7 +27,7 @@ void VolumeManager::setVolume(float volume) volume = max(10.f, min(volume, m_maximumVolumePercent)); m_currentVolumePercent = volume; - m_volumePublisher.publish(volumeToMsg(m_currentVolumePercent)); + m_volumePublisher->publish(volumeToMsg(m_currentVolumePercent)); } float VolumeManager::getVolume() const @@ -29,15 +35,15 @@ float VolumeManager::getVolume() const return m_currentVolumePercent; } -void VolumeManager::baseStatusSubscriberCallback(const daemon_ros_client::BaseStatus::ConstPtr& msg) +void VolumeManager::baseStatusSubscriberCallback(const daemon_ros_client::msg::BaseStatus::SharedPtr msg) { m_currentVolumePercent = volumeIntToPercent(msg->volume); m_maximumVolumePercent = volumeIntToPercent(msg->maximum_volume); } -std_msgs::UInt8 VolumeManager::volumeToMsg(float volumePercent) +std_msgs::msg::UInt8 VolumeManager::volumeToMsg(float volumePercent) { - std_msgs::UInt8 msg; + std_msgs::msg::UInt8 msg; msg.data = volumePercentToInt(volumePercent); return msg; } diff --git a/ros/demos/home_logger/src/managers/VolumeManager.h b/ros/demos/home_logger/src/managers/VolumeManager.h index 190306fc..833bc599 100644 --- a/ros/demos/home_logger/src/managers/VolumeManager.h +++ b/ros/demos/home_logger/src/managers/VolumeManager.h @@ -1,22 +1,24 @@ #ifndef HOME_LOGGER_MANAGERS_VOLUME_MANAGER_H #define HOME_LOGGER_MANAGERS_VOLUME_MANAGER_H -#include -#include -#include +#include +#include +#include #include class VolumeManager { + rclcpp::Node::SharedPtr m_node; + float m_currentVolumePercent; float m_maximumVolumePercent; - ros::Publisher m_volumePublisher; - ros::Subscriber m_baseStatusSubscriber; + rclcpp::Publisher::SharedPtr m_volumePublisher; + rclcpp::Subscription::SharedPtr m_baseStatusSubscriber; public: - VolumeManager(ros::NodeHandle& nodeHandle); + VolumeManager(rclcpp::Node::SharedPtr node); virtual ~VolumeManager(); DECLARE_NOT_COPYABLE(VolumeManager); @@ -26,9 +28,9 @@ class VolumeManager float getVolume() const; private: - void baseStatusSubscriberCallback(const daemon_ros_client::BaseStatus::ConstPtr& msg); + void baseStatusSubscriberCallback(const daemon_ros_client::msg::BaseStatus::SharedPtr msg); - std_msgs::UInt8 volumeToMsg(float volumePercent); + std_msgs::msg::UInt8 volumeToMsg(float volumePercent); float volumeIntToPercent(uint8_t v); uint8_t volumePercentToInt(float v); }; diff --git a/ros/demos/home_logger/src/states/State.cpp b/ros/demos/home_logger/src/states/State.cpp index 6eb89414..6302c4d4 100644 --- a/ros/demos/home_logger/src/states/State.cpp +++ b/ros/demos/home_logger/src/states/State.cpp @@ -15,11 +15,11 @@ string StateParameter::toString() const StateType::StateType(type_index type) : m_type(type) {} -State::State(StateManager& stateManager, shared_ptr desireSet, ros::NodeHandle& nodeHandle) +State::State(StateManager& stateManager, shared_ptr desireSet, rclcpp::Node::SharedPtr node) : m_enabled(false), m_stateManager(stateManager), m_desireSet(desireSet), - m_nodeHandle(nodeHandle) + m_node(move(node)) { } @@ -45,19 +45,17 @@ void State::disable() void State::onDesireSetChanged(const vector>& desires) {} -void State::onSpeechToTextTranscriptReceived(const speech_to_text::Transcript::ConstPtr& msg) {} +void State::onSpeechToTextTranscriptReceived(const perception_msgs::msg::Transcript::SharedPtr& msg) {} void State::onRobotNameDetected() {} -void State::onVideoAnalysisReceived(const video_analyzer::VideoAnalysis::ConstPtr& msg) {} +void State::onVideoAnalysisReceived(const perception_msgs::msg::VideoAnalysis::SharedPtr& msg) {} -void State::onAudioAnalysisReceived(const audio_analyzer::AudioAnalysis::ConstPtr& msg) {} +void State::onAudioAnalysisReceived(const perception_msgs::msg::AudioAnalysis::SharedPtr& msg) {} -void State::onPersonNamesDetected(const person_identification::PersonNames::ConstPtr& msg) {} +void State::onPersonNamesDetected(const perception_msgs::msg::PersonNames::SharedPtr& msg) {} -void State::onBaseStatusChanged(const daemon_ros_client::BaseStatus::ConstPtr& msg) -{ -} +void State::onBaseStatusChanged(const daemon_ros_client::msg::BaseStatus::SharedPtr& msg) {} void State::onStateTimeout() {} @@ -66,7 +64,7 @@ void State::onEveryMinuteTimeout() {} void State::onEveryTenMinutesTimeout() {} -bool containsAtLeastOnePerson(const video_analyzer::VideoAnalysis::ConstPtr& msg) +bool containsAtLeastOnePerson(const perception_msgs::msg::VideoAnalysis::SharedPtr& msg) { for (auto& object : msg->objects) { diff --git a/ros/demos/home_logger/src/states/State.h b/ros/demos/home_logger/src/states/State.h index 62361903..bbf2a163 100644 --- a/ros/demos/home_logger/src/states/State.h +++ b/ros/demos/home_logger/src/states/State.h @@ -1,18 +1,18 @@ #ifndef HOME_LOGGER_STATES_STATE_H #define HOME_LOGGER_STATES_STATE_H -#include +#include -#include -#include +#include +#include #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include @@ -117,7 +117,10 @@ namespace std } #define DECLARE_STATE_PROTECTED_METHODS(className) \ - StateType type() const override { return StateType::get(); } + StateType type() const override \ + { \ + return StateType::get(); \ + } class State { @@ -126,10 +129,10 @@ class State protected: StateManager& m_stateManager; std::shared_ptr m_desireSet; - ros::NodeHandle& m_nodeHandle; + rclcpp::Node::SharedPtr m_node; public: - State(StateManager& stateManager, std::shared_ptr desireSet, ros::NodeHandle& nodeHandle); + State(StateManager& stateManager, std::shared_ptr desireSet, rclcpp::Node::SharedPtr node); virtual ~State(); DECLARE_NOT_COPYABLE(State); @@ -147,12 +150,12 @@ class State virtual void onDesireSetChanged(const std::vector>& desires); - virtual void onSpeechToTextTranscriptReceived(const speech_to_text::Transcript::ConstPtr& msg); + virtual void onSpeechToTextTranscriptReceived(const perception_msgs::msg::Transcript::SharedPtr& msg); virtual void onRobotNameDetected(); - virtual void onVideoAnalysisReceived(const video_analyzer::VideoAnalysis::ConstPtr& msg); - virtual void onAudioAnalysisReceived(const audio_analyzer::AudioAnalysis::ConstPtr& msg); - virtual void onPersonNamesDetected(const person_identification::PersonNames::ConstPtr& msg); - virtual void onBaseStatusChanged(const daemon_ros_client::BaseStatus::ConstPtr& msg); + virtual void onVideoAnalysisReceived(const perception_msgs::msg::VideoAnalysis::SharedPtr& msg); + virtual void onAudioAnalysisReceived(const perception_msgs::msg::AudioAnalysis::SharedPtr& msg); + virtual void onPersonNamesDetected(const perception_msgs::msg::PersonNames::SharedPtr& msg); + virtual void onBaseStatusChanged(const daemon_ros_client::msg::BaseStatus::SharedPtr& msg); virtual void onStateTimeout(); virtual void onEveryMinuteTimeout(); @@ -166,6 +169,6 @@ inline bool State::enabled() const return m_enabled; } -bool containsAtLeastOnePerson(const video_analyzer::VideoAnalysis::ConstPtr& msg); +bool containsAtLeastOnePerson(const perception_msgs::msg::VideoAnalysis::SharedPtr& msg); #endif diff --git a/ros/demos/home_logger/src/states/StateManager.cpp b/ros/demos/home_logger/src/states/StateManager.cpp index fc9c0556..aea28f40 100644 --- a/ros/demos/home_logger/src/states/StateManager.cpp +++ b/ros/demos/home_logger/src/states/StateManager.cpp @@ -2,30 +2,45 @@ using namespace std; -const double TIMEOUT_S = 30.0; -const double ONE_MINUTE_S = 60.0; -const double TEN_MINUTES_S = 600.0; +const int TIMEOUT_S = 30; +const int ONE_MINUTE_S = 60; +const int TEN_MINUTES_S = 600; -StateManager::StateManager(shared_ptr desireSet, ros::NodeHandle& nodeHandle) +StateManager::StateManager(shared_ptr desireSet, rclcpp::Node::SharedPtr node) : m_desireSet(desireSet), - m_nodeHandle(nodeHandle), + m_node(move(node)), m_currentState(nullptr) { m_desireSet->addObserver(this); - m_speechToTextSubscriber = - nodeHandle.subscribe("speech_to_text/transcript", 1, &StateManager::onSpeechToTextTranscriptReceived, this); - m_robotNameDetectedSubscriber = - nodeHandle.subscribe("robot_name_detected", 1, &StateManager::onRobotNameDetected, this); - m_videoAnalysisSubscriber = nodeHandle.subscribe("video_analysis", 1, &StateManager::onVideoAnalysisReceived, this); - m_audioAnalysisSubscriber = nodeHandle.subscribe("audio_analysis", 1, &StateManager::onAudioAnalysisReceived, this); - m_personNamesSubscriber = nodeHandle.subscribe("person_names", 1, &StateManager::onPersonNamesDetected, this); - m_baseStatusSubscriber = nodeHandle.subscribe("daemon/base_status", 1, &StateManager::onBaseStatusChanged, this); - - m_everyMinuteTimer = - m_nodeHandle.createTimer(ros::Duration(ONE_MINUTE_S), &StateManager::onEveryMinuteTimeout, this); + m_speechToTextSubscriber = m_node->create_subscription( + "speech_to_text/transcript", + 1, + [this](const perception_msgs::msg::Transcript::SharedPtr msg) { onSpeechToTextTranscriptReceived(msg); }); + m_robotNameDetectedSubscriber = m_node->create_subscription( + "robot_name_detected", + 1, + [this](const std_msgs::msg::Empty::SharedPtr msg) { onRobotNameDetected(msg); }); + m_videoAnalysisSubscriber = m_node->create_subscription( + "video_analysis", + 1, + [this](const perception_msgs::msg::VideoAnalysis::SharedPtr msg) { onVideoAnalysisReceived(msg); }); + m_audioAnalysisSubscriber = m_node->create_subscription( + "audio_analysis", + 1, + [this](const perception_msgs::msg::AudioAnalysis::SharedPtr msg) { onAudioAnalysisReceived(msg); }); + m_personNamesSubscriber = m_node->create_subscription( + "person_names", + 1, + [this](const perception_msgs::msg::PersonNames::SharedPtr msg) { onPersonNamesDetected(msg); }); + m_baseStatusSubscriber = m_node->create_subscription( + "daemon/base_status", + 1, + [this](const daemon_ros_client::msg::BaseStatus::SharedPtr msg) { onBaseStatusChanged(msg); }); + + m_everyMinuteTimer = m_node->create_wall_timer(chrono::seconds(ONE_MINUTE_S), [this]() { onEveryMinuteTimeout(); }); m_everyTenMinuteTimer = - m_nodeHandle.createTimer(ros::Duration(TEN_MINUTES_S), &StateManager::onEveryTenMinutesTimeout, this); + m_node->create_wall_timer(chrono::seconds(TEN_MINUTES_S), [this]() { onEveryTenMinutesTimeout(); }); } StateManager::~StateManager() @@ -40,9 +55,10 @@ void StateManager::addState(unique_ptr state) void StateManager::switchTo(StateType type, const StateParameter& parameter) { - if (m_stateTimeoutTimer.isValid()) + if (m_stateTimeoutTimer) { - m_stateTimeoutTimer.stop(); + m_stateTimeoutTimer->cancel(); + m_stateTimeoutTimer = nullptr; } auto transaction = m_desireSet->beginTransaction(); @@ -50,18 +66,16 @@ void StateManager::switchTo(StateType type, const StateParameter& parameter) StateType previousStateType = StateType::null(); if (m_currentState != nullptr) { - ROS_INFO_STREAM("Disabling " << m_currentState->type().name()); + RCLCPP_INFO_STREAM(m_node->get_logger(), "Disabling " << m_currentState->type().name()); m_currentState->disable(); previousStateType = m_currentState->type(); } - ROS_INFO_STREAM("Enabling " << type.name() << "(" << parameter.toString() << ")"); + RCLCPP_INFO_STREAM(m_node->get_logger(), "Enabling " << type.name() << "(" << parameter.toString() << ")"); m_currentState = m_states.at(type).get(); m_currentState->enable(parameter, previousStateType); - constexpr bool ONE_SHOT = true; - m_stateTimeoutTimer = - m_nodeHandle.createTimer(ros::Duration(TIMEOUT_S), &StateManager::onStateTimeout, this, ONE_SHOT); + m_stateTimeoutTimer = m_node->create_wall_timer(chrono::seconds(TIMEOUT_S), [this]() { onStateTimeout(); }); } void StateManager::onDesireSetChanged(const vector>& desires) @@ -72,7 +86,7 @@ void StateManager::onDesireSetChanged(const vector>& desires) } } -void StateManager::onSpeechToTextTranscriptReceived(const speech_to_text::Transcript::ConstPtr& msg) +void StateManager::onSpeechToTextTranscriptReceived(const perception_msgs::msg::Transcript::SharedPtr& msg) { if (m_currentState != nullptr) { @@ -80,7 +94,7 @@ void StateManager::onSpeechToTextTranscriptReceived(const speech_to_text::Transc } } -void StateManager::onRobotNameDetected(const std_msgs::Empty::ConstPtr& msg) +void StateManager::onRobotNameDetected(const std_msgs::msg::Empty::SharedPtr& msg) { if (m_currentState != nullptr) { @@ -88,7 +102,7 @@ void StateManager::onRobotNameDetected(const std_msgs::Empty::ConstPtr& msg) } } -void StateManager::onVideoAnalysisReceived(const video_analyzer::VideoAnalysis::ConstPtr& msg) +void StateManager::onVideoAnalysisReceived(const perception_msgs::msg::VideoAnalysis::SharedPtr& msg) { if (m_currentState != nullptr) { @@ -96,7 +110,7 @@ void StateManager::onVideoAnalysisReceived(const video_analyzer::VideoAnalysis:: } } -void StateManager::onAudioAnalysisReceived(const audio_analyzer::AudioAnalysis::ConstPtr& msg) +void StateManager::onAudioAnalysisReceived(const perception_msgs::msg::AudioAnalysis::SharedPtr& msg) { if (m_currentState != nullptr) { @@ -104,7 +118,7 @@ void StateManager::onAudioAnalysisReceived(const audio_analyzer::AudioAnalysis:: } } -void StateManager::onPersonNamesDetected(const person_identification::PersonNames::ConstPtr& msg) +void StateManager::onPersonNamesDetected(const perception_msgs::msg::PersonNames::SharedPtr& msg) { if (m_currentState != nullptr) { @@ -112,7 +126,7 @@ void StateManager::onPersonNamesDetected(const person_identification::PersonName } } -void StateManager::onBaseStatusChanged(const daemon_ros_client::BaseStatus::ConstPtr& msg) +void StateManager::onBaseStatusChanged(const daemon_ros_client::msg::BaseStatus::SharedPtr& msg) { if (m_currentState != nullptr) { @@ -120,7 +134,7 @@ void StateManager::onBaseStatusChanged(const daemon_ros_client::BaseStatus::Cons } } -void StateManager::onStateTimeout(const ros::TimerEvent& event) +void StateManager::onStateTimeout() { if (m_currentState != nullptr) { @@ -128,7 +142,7 @@ void StateManager::onStateTimeout(const ros::TimerEvent& event) } } -void StateManager::onEveryMinuteTimeout(const ros::TimerEvent& event) +void StateManager::onEveryMinuteTimeout() { if (m_currentState != nullptr) { @@ -136,7 +150,7 @@ void StateManager::onEveryMinuteTimeout(const ros::TimerEvent& event) } } -void StateManager::onEveryTenMinutesTimeout(const ros::TimerEvent& event) +void StateManager::onEveryTenMinutesTimeout() { if (m_currentState != nullptr) { diff --git a/ros/demos/home_logger/src/states/StateManager.h b/ros/demos/home_logger/src/states/StateManager.h index 16a196b7..2f9f4a8a 100644 --- a/ros/demos/home_logger/src/states/StateManager.h +++ b/ros/demos/home_logger/src/states/StateManager.h @@ -8,24 +8,24 @@ class StateManager : private DesireSetObserver { std::shared_ptr m_desireSet; - ros::NodeHandle& m_nodeHandle; + rclcpp::Node::SharedPtr m_node; std::unordered_map> m_states; State* m_currentState; - ros::Subscriber m_speechToTextSubscriber; - ros::Subscriber m_robotNameDetectedSubscriber; - ros::Subscriber m_videoAnalysisSubscriber; - ros::Subscriber m_audioAnalysisSubscriber; - ros::Subscriber m_personNamesSubscriber; - ros::Subscriber m_baseStatusSubscriber; + rclcpp::Subscription::SharedPtr m_speechToTextSubscriber; + rclcpp::Subscription::SharedPtr m_robotNameDetectedSubscriber; + rclcpp::Subscription::SharedPtr m_videoAnalysisSubscriber; + rclcpp::Subscription::SharedPtr m_audioAnalysisSubscriber; + rclcpp::Subscription::SharedPtr m_personNamesSubscriber; + rclcpp::Subscription::SharedPtr m_baseStatusSubscriber; - ros::Timer m_stateTimeoutTimer; - ros::Timer m_everyMinuteTimer; - ros::Timer m_everyTenMinuteTimer; + rclcpp::TimerBase::SharedPtr m_stateTimeoutTimer; + rclcpp::TimerBase::SharedPtr m_everyMinuteTimer; + rclcpp::TimerBase::SharedPtr m_everyTenMinuteTimer; public: - StateManager(std::shared_ptr desireSet, ros::NodeHandle& nodeHandle); + StateManager(std::shared_ptr desireSet, rclcpp::Node::SharedPtr node); virtual ~StateManager(); DECLARE_NOT_COPYABLE(StateManager); @@ -40,16 +40,16 @@ class StateManager : private DesireSetObserver private: void onDesireSetChanged(const std::vector>& desires) override; - void onSpeechToTextTranscriptReceived(const speech_to_text::Transcript::ConstPtr& msg); - void onRobotNameDetected(const std_msgs::Empty::ConstPtr& msg); - void onVideoAnalysisReceived(const video_analyzer::VideoAnalysis::ConstPtr& msg); - void onAudioAnalysisReceived(const audio_analyzer::AudioAnalysis::ConstPtr& msg); - void onPersonNamesDetected(const person_identification::PersonNames::ConstPtr& msg); - void onBaseStatusChanged(const daemon_ros_client::BaseStatus::ConstPtr& msg); + void onSpeechToTextTranscriptReceived(const perception_msgs::msg::Transcript::SharedPtr& msg); + void onRobotNameDetected(const std_msgs::msg::Empty::SharedPtr& msg); + void onVideoAnalysisReceived(const perception_msgs::msg::VideoAnalysis::SharedPtr& msg); + void onAudioAnalysisReceived(const perception_msgs::msg::AudioAnalysis::SharedPtr& msg); + void onPersonNamesDetected(const perception_msgs::msg::PersonNames::SharedPtr& msg); + void onBaseStatusChanged(const daemon_ros_client::msg::BaseStatus::SharedPtr& msg); - void onStateTimeout(const ros::TimerEvent& event); - void onEveryMinuteTimeout(const ros::TimerEvent& event); - void onEveryTenMinutesTimeout(const ros::TimerEvent& event); + void onStateTimeout(); + void onEveryMinuteTimeout(); + void onEveryTenMinutesTimeout(); }; template diff --git a/ros/demos/home_logger/src/states/common/SoundFaceFollowingState.cpp b/ros/demos/home_logger/src/states/common/SoundFaceFollowingState.cpp index 57ca4c48..8d18249c 100644 --- a/ros/demos/home_logger/src/states/common/SoundFaceFollowingState.cpp +++ b/ros/demos/home_logger/src/states/common/SoundFaceFollowingState.cpp @@ -9,8 +9,8 @@ using namespace std; SoundFaceFollowingState::SoundFaceFollowingState( StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle) - : State(stateManager, move(desireSet), nodeHandle), + rclcpp::Node::SharedPtr node) + : State(stateManager, move(desireSet), move(node)), m_followingDesireType(DesireType::null()), m_videoAnalysisWithoutPersonCount(0) { @@ -29,7 +29,7 @@ void SoundFaceFollowingState::onDisabling() setFollowingDesire(nullptr); } -void SoundFaceFollowingState::onVideoAnalysisReceived(const video_analyzer::VideoAnalysis::ConstPtr& msg) +void SoundFaceFollowingState::onVideoAnalysisReceived(const perception_msgs::msg::VideoAnalysis::SharedPtr& msg) { bool containsAPerson = containsAtLeastOnePerson(msg); diff --git a/ros/demos/home_logger/src/states/common/SoundFaceFollowingState.h b/ros/demos/home_logger/src/states/common/SoundFaceFollowingState.h index 6ddd735a..89560fae 100644 --- a/ros/demos/home_logger/src/states/common/SoundFaceFollowingState.h +++ b/ros/demos/home_logger/src/states/common/SoundFaceFollowingState.h @@ -15,7 +15,7 @@ class SoundFaceFollowingState : public State SoundFaceFollowingState( StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle); + rclcpp::Node::SharedPtr node); ~SoundFaceFollowingState() override; protected: @@ -24,7 +24,7 @@ class SoundFaceFollowingState : public State void onEnabling(const StateParameter& parameter, const StateType& previousStateType) override; void onDisabling() override; - void onVideoAnalysisReceived(const video_analyzer::VideoAnalysis::ConstPtr& msg) override; + void onVideoAnalysisReceived(const perception_msgs::msg::VideoAnalysis::SharedPtr& msg) override; private: void setFollowingDesire(std::unique_ptr desire); diff --git a/ros/demos/home_logger/src/states/common/TalkState.cpp b/ros/demos/home_logger/src/states/common/TalkState.cpp index 9cf6d01b..4638823d 100644 --- a/ros/demos/home_logger/src/states/common/TalkState.cpp +++ b/ros/demos/home_logger/src/states/common/TalkState.cpp @@ -60,8 +60,8 @@ string TalkStateParameter::toString() const } -TalkState::TalkState(StateManager& stateManager, shared_ptr desireSet, ros::NodeHandle& nodeHandle) - : State(stateManager, move(desireSet), nodeHandle) +TalkState::TalkState(StateManager& stateManager, shared_ptr desireSet, rclcpp::Node::SharedPtr node) + : State(stateManager, move(desireSet), move(node)) { } diff --git a/ros/demos/home_logger/src/states/common/TalkState.h b/ros/demos/home_logger/src/states/common/TalkState.h index c9bf840a..f3c2c33f 100644 --- a/ros/demos/home_logger/src/states/common/TalkState.h +++ b/ros/demos/home_logger/src/states/common/TalkState.h @@ -39,7 +39,7 @@ class TalkState : public State std::optional m_faceAnimationDesireId; public: - TalkState(StateManager& stateManager, std::shared_ptr desireSet, ros::NodeHandle& nodeHandle); + TalkState(StateManager& stateManager, std::shared_ptr desireSet, rclcpp::Node::SharedPtr node); ~TalkState() override; protected: diff --git a/ros/demos/home_logger/src/states/specific/AlarmState.cpp b/ros/demos/home_logger/src/states/specific/AlarmState.cpp index e4bf7e26..9bc1357f 100644 --- a/ros/demos/home_logger/src/states/specific/AlarmState.cpp +++ b/ros/demos/home_logger/src/states/specific/AlarmState.cpp @@ -22,10 +22,10 @@ string AlarmStateParameter::toString() const AlarmState::AlarmState( StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, AlarmManager& alarmManager, string alarmPath) - : SoundFaceFollowingState(stateManager, move(desireSet), nodeHandle), + : SoundFaceFollowingState(stateManager, move(desireSet), move(node)), m_alarmManager(alarmManager), m_alarmPath(move(alarmPath)) { diff --git a/ros/demos/home_logger/src/states/specific/AlarmState.h b/ros/demos/home_logger/src/states/specific/AlarmState.h index 9f6f2141..591c4914 100644 --- a/ros/demos/home_logger/src/states/specific/AlarmState.h +++ b/ros/demos/home_logger/src/states/specific/AlarmState.h @@ -29,7 +29,7 @@ class AlarmState : public SoundFaceFollowingState AlarmState( StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, AlarmManager& alarmManager, std::string alarmPath); ~AlarmState() override; diff --git a/ros/demos/home_logger/src/states/specific/ExecuteCommandState.cpp b/ros/demos/home_logger/src/states/specific/ExecuteCommandState.cpp index 31900b3c..6efc9816 100644 --- a/ros/demos/home_logger/src/states/specific/ExecuteCommandState.cpp +++ b/ros/demos/home_logger/src/states/specific/ExecuteCommandState.cpp @@ -42,12 +42,12 @@ string ExecuteCommandStateParameter::toString() const ExecuteCommandState::ExecuteCommandState( StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, VolumeManager& volumeManager, AlarmManager& alarmManager, ReminderManager& reminderManager) - : SoundFaceFollowingState(stateManager, move(desireSet), nodeHandle), - m_allCommandExecutor(stateManager, nodeHandle, volumeManager, alarmManager, reminderManager), + : SoundFaceFollowingState(stateManager, move(desireSet), node), + m_allCommandExecutor(stateManager, node, volumeManager, alarmManager, reminderManager), m_allCommandParametersAsker(stateManager) { } diff --git a/ros/demos/home_logger/src/states/specific/ExecuteCommandState.h b/ros/demos/home_logger/src/states/specific/ExecuteCommandState.h index 913f5be7..5d8838f3 100644 --- a/ros/demos/home_logger/src/states/specific/ExecuteCommandState.h +++ b/ros/demos/home_logger/src/states/specific/ExecuteCommandState.h @@ -39,7 +39,7 @@ class ExecuteCommandState : public SoundFaceFollowingState ExecuteCommandState( StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, VolumeManager& volumeManager, AlarmManager& alarmManager, ReminderManager& reminderManager); diff --git a/ros/demos/home_logger/src/states/specific/IdleState.cpp b/ros/demos/home_logger/src/states/specific/IdleState.cpp index 0327cb27..5db37a05 100644 --- a/ros/demos/home_logger/src/states/specific/IdleState.cpp +++ b/ros/demos/home_logger/src/states/specific/IdleState.cpp @@ -19,13 +19,13 @@ constexpr chrono::hours GREATING_INTERVAL(4); IdleState::IdleState( StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, AlarmManager& alarmManager, ReminderManager& reminderManager, Time sleepTime, Time wakeUpTime, float faceDescriptorThreshold) - : SoundFaceFollowingState(stateManager, move(desireSet), nodeHandle), + : SoundFaceFollowingState(stateManager, move(desireSet), move(node)), m_alarmManager(alarmManager), m_reminderManager(reminderManager), m_sleepTime(sleepTime), @@ -73,7 +73,7 @@ void IdleState::onDisabling() } } -void IdleState::onVideoAnalysisReceived(const video_analyzer::VideoAnalysis::ConstPtr& msg) +void IdleState::onVideoAnalysisReceived(const perception_msgs::msg::VideoAnalysis::SharedPtr& msg) { SoundFaceFollowingState::onVideoAnalysisReceived(msg); @@ -119,7 +119,7 @@ void IdleState::onRobotNameDetected() StateType::get())); } -void IdleState::onBaseStatusChanged(const daemon_ros_client::BaseStatus::ConstPtr& msg) +void IdleState::onBaseStatusChanged(const daemon_ros_client::msg::BaseStatus::SharedPtr& msg) { m_chargeNeeded = msg->state_of_charge <= LOW_STATE_OF_CHARGE && !msg->is_psu_connected; } @@ -147,7 +147,7 @@ void IdleState::onEveryTenMinutesTimeout() m_todayReminders = m_reminderManager.listReminders(Date::now()); } -optional IdleState::findReminder(const video_analyzer::VideoAnalysis::ConstPtr& msg) +optional IdleState::findReminder(const perception_msgs::msg::VideoAnalysis::SharedPtr& msg) { for (auto& object : msg->objects) { diff --git a/ros/demos/home_logger/src/states/specific/IdleState.h b/ros/demos/home_logger/src/states/specific/IdleState.h index 91f5b4af..c71755d1 100644 --- a/ros/demos/home_logger/src/states/specific/IdleState.h +++ b/ros/demos/home_logger/src/states/specific/IdleState.h @@ -32,7 +32,7 @@ class IdleState : public SoundFaceFollowingState IdleState( StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, AlarmManager& alarmManager, ReminderManager& reminderManager, Time sleepTime, @@ -46,14 +46,14 @@ class IdleState : public SoundFaceFollowingState void onEnabling(const StateParameter& parameter, const StateType& previousStateType) override; void onDisabling() override; - void onVideoAnalysisReceived(const video_analyzer::VideoAnalysis::ConstPtr& msg) override; + void onVideoAnalysisReceived(const perception_msgs::msg::VideoAnalysis::SharedPtr& msg) override; void onRobotNameDetected() override; - void onBaseStatusChanged(const daemon_ros_client::BaseStatus::ConstPtr& msg) override; + void onBaseStatusChanged(const daemon_ros_client::msg::BaseStatus::SharedPtr& msg) override; void onEveryMinuteTimeout() override; void onEveryTenMinutesTimeout() override; private: - std::optional findReminder(const video_analyzer::VideoAnalysis::ConstPtr& msg); + std::optional findReminder(const perception_msgs::msg::VideoAnalysis::SharedPtr& msg); void switchToAlarmState(std::vector> alarms); }; diff --git a/ros/demos/home_logger/src/states/specific/SleepState.cpp b/ros/demos/home_logger/src/states/specific/SleepState.cpp index d71c7de0..134155e6 100644 --- a/ros/demos/home_logger/src/states/specific/SleepState.cpp +++ b/ros/demos/home_logger/src/states/specific/SleepState.cpp @@ -9,10 +9,10 @@ using namespace std; SleepState::SleepState( StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, Time sleepTime, Time wakeUpTime) - : State(stateManager, move(desireSet), nodeHandle), + : State(stateManager, move(desireSet), move(node)), m_sleepTime(sleepTime), m_wakeUpTime(wakeUpTime), m_wasForced(false), diff --git a/ros/demos/home_logger/src/states/specific/SleepState.h b/ros/demos/home_logger/src/states/specific/SleepState.h index 516bfda5..204f8695 100644 --- a/ros/demos/home_logger/src/states/specific/SleepState.h +++ b/ros/demos/home_logger/src/states/specific/SleepState.h @@ -26,7 +26,7 @@ class SleepState : public State SleepState( StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, Time sleepTime, Time wakeUpTime); ~SleepState() override; diff --git a/ros/demos/home_logger/src/states/specific/TellReminderState.cpp b/ros/demos/home_logger/src/states/specific/TellReminderState.cpp index 3e89076c..a189525a 100644 --- a/ros/demos/home_logger/src/states/specific/TellReminderState.cpp +++ b/ros/demos/home_logger/src/states/specific/TellReminderState.cpp @@ -24,9 +24,9 @@ string TellReminderStateParameter::toString() const TellReminderState::TellReminderState( StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, ReminderManager& reminderManager) - : TalkState(stateManager, desireSet, nodeHandle), + : TalkState(stateManager, desireSet, move(node)), m_reminderManager(reminderManager) { } diff --git a/ros/demos/home_logger/src/states/specific/TellReminderState.h b/ros/demos/home_logger/src/states/specific/TellReminderState.h index 2f58dfd9..ead945e9 100644 --- a/ros/demos/home_logger/src/states/specific/TellReminderState.h +++ b/ros/demos/home_logger/src/states/specific/TellReminderState.h @@ -27,7 +27,7 @@ class TellReminderState : public TalkState TellReminderState( StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, ReminderManager& reminderManager); ~TellReminderState() override; diff --git a/ros/demos/home_logger/src/states/specific/WaitCommandParameterState.cpp b/ros/demos/home_logger/src/states/specific/WaitCommandParameterState.cpp index 58934351..d26ac167 100644 --- a/ros/demos/home_logger/src/states/specific/WaitCommandParameterState.cpp +++ b/ros/demos/home_logger/src/states/specific/WaitCommandParameterState.cpp @@ -32,8 +32,8 @@ string WaitCommandParameterStateParameter::toString() const WaitCommandParameterState::WaitCommandParameterState( StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle) - : SoundFaceFollowingState(stateManager, move(desireSet), nodeHandle), + rclcpp::Node::SharedPtr node) + : SoundFaceFollowingState(stateManager, move(desireSet), move(node)), m_transcriptReceived(false) { } @@ -69,7 +69,7 @@ void WaitCommandParameterState::onDisabling() } } -void WaitCommandParameterState::onSpeechToTextTranscriptReceived(const speech_to_text::Transcript::ConstPtr& msg) +void WaitCommandParameterState::onSpeechToTextTranscriptReceived(const perception_msgs::msg::Transcript::SharedPtr& msg) { m_transcriptReceived = true; m_parameterResponse = msg->text; diff --git a/ros/demos/home_logger/src/states/specific/WaitCommandParameterState.h b/ros/demos/home_logger/src/states/specific/WaitCommandParameterState.h index 9602da1c..2afec15b 100644 --- a/ros/demos/home_logger/src/states/specific/WaitCommandParameterState.h +++ b/ros/demos/home_logger/src/states/specific/WaitCommandParameterState.h @@ -32,7 +32,7 @@ class WaitCommandParameterState : public SoundFaceFollowingState WaitCommandParameterState( StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle); + rclcpp::Node::SharedPtr node); ~WaitCommandParameterState() override; protected: @@ -41,7 +41,7 @@ class WaitCommandParameterState : public SoundFaceFollowingState void onEnabling(const StateParameter& parameter, const StateType& previousStateType) override; void onDisabling() override; - void onSpeechToTextTranscriptReceived(const speech_to_text::Transcript::ConstPtr& msg) override; + void onSpeechToTextTranscriptReceived(const perception_msgs::msg::Transcript::SharedPtr& msg) override; void onStateTimeout() override; private: diff --git a/ros/demos/home_logger/src/states/specific/WaitCommandState.cpp b/ros/demos/home_logger/src/states/specific/WaitCommandState.cpp index f07d25ea..de35c529 100644 --- a/ros/demos/home_logger/src/states/specific/WaitCommandState.cpp +++ b/ros/demos/home_logger/src/states/specific/WaitCommandState.cpp @@ -13,8 +13,8 @@ using namespace std; WaitCommandState::WaitCommandState( StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle) - : SoundFaceFollowingState(stateManager, move(desireSet), nodeHandle), + rclcpp::Node::SharedPtr node) + : SoundFaceFollowingState(stateManager, move(desireSet), move(node)), m_transcriptReceived(false) { } @@ -48,7 +48,7 @@ void WaitCommandState::onDisabling() } } -void WaitCommandState::onSpeechToTextTranscriptReceived(const speech_to_text::Transcript::ConstPtr& msg) +void WaitCommandState::onSpeechToTextTranscriptReceived(const perception_msgs::msg::Transcript::SharedPtr& msg) { m_transcriptReceived = true; m_commands = m_parser.parse(msg->text); diff --git a/ros/demos/home_logger/src/states/specific/WaitCommandState.h b/ros/demos/home_logger/src/states/specific/WaitCommandState.h index 11c0f8ba..124d9d69 100644 --- a/ros/demos/home_logger/src/states/specific/WaitCommandState.h +++ b/ros/demos/home_logger/src/states/specific/WaitCommandState.h @@ -15,7 +15,7 @@ class WaitCommandState : public SoundFaceFollowingState std::optional m_speechToTextDesireId; public: - WaitCommandState(StateManager& stateManager, std::shared_ptr desireSet, ros::NodeHandle& nodeHandle); + WaitCommandState(StateManager& stateManager, std::shared_ptr desireSet, rclcpp::Node::SharedPtr node); ~WaitCommandState() override; protected: @@ -24,7 +24,7 @@ class WaitCommandState : public SoundFaceFollowingState void onEnabling(const StateParameter& parameter, const StateType& previousStateType) override; void onDisabling() override; - void onSpeechToTextTranscriptReceived(const speech_to_text::Transcript::ConstPtr& msg) override; + void onSpeechToTextTranscriptReceived(const perception_msgs::msg::Transcript::SharedPtr& msg) override; void onStateTimeout() override; private: diff --git a/ros/demos/home_logger/src/states/specific/WaitFaceDescriptorCommandParameterState.cpp b/ros/demos/home_logger/src/states/specific/WaitFaceDescriptorCommandParameterState.cpp index 048ef112..a5996024 100644 --- a/ros/demos/home_logger/src/states/specific/WaitFaceDescriptorCommandParameterState.cpp +++ b/ros/demos/home_logger/src/states/specific/WaitFaceDescriptorCommandParameterState.cpp @@ -5,7 +5,8 @@ #include #include -#include + +#include using namespace std; @@ -32,9 +33,9 @@ string WaitFaceDescriptorCommandParameterStateParameter::toString() const WaitFaceDescriptorCommandParameterState::WaitFaceDescriptorCommandParameterState( StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, float noseConfidenceThreshold) - : SoundFaceFollowingState(stateManager, move(desireSet), nodeHandle), + : SoundFaceFollowingState(stateManager, move(desireSet), move(node)), m_noseConfidenceThreshold(noseConfidenceThreshold) { } @@ -74,7 +75,7 @@ void WaitFaceDescriptorCommandParameterState::onDisabling() } void WaitFaceDescriptorCommandParameterState::onVideoAnalysisReceived( - const video_analyzer::VideoAnalysis::ConstPtr& msg) + const perception_msgs::msg::VideoAnalysis::SharedPtr& msg) { auto faceDescriptor = findNearestFaceDescriptor(msg); if (faceDescriptor.has_value()) @@ -94,7 +95,7 @@ void WaitFaceDescriptorCommandParameterState::onStateTimeout() } optional WaitFaceDescriptorCommandParameterState::findNearestFaceDescriptor( - const video_analyzer::VideoAnalysis::ConstPtr& msg) + const perception_msgs::msg::VideoAnalysis::SharedPtr& msg) { constexpr size_t PERSON_POSE_NOSE_INDEX = 0; @@ -111,7 +112,7 @@ optional WaitFaceDescriptorCommandParameterState::findNearestFac } auto nosePoint = object.person_pose_3d[PERSON_POSE_NOSE_INDEX]; - float distance = tf::Vector3(nosePoint.x, nosePoint.y, nosePoint.z).length(); + float distance = tf2::Vector3(nosePoint.x, nosePoint.y, nosePoint.z).length(); if (distance < nearestDistance) { nearestDistance = distance; diff --git a/ros/demos/home_logger/src/states/specific/WaitFaceDescriptorCommandParameterState.h b/ros/demos/home_logger/src/states/specific/WaitFaceDescriptorCommandParameterState.h index 548eeff1..474c7ce5 100644 --- a/ros/demos/home_logger/src/states/specific/WaitFaceDescriptorCommandParameterState.h +++ b/ros/demos/home_logger/src/states/specific/WaitFaceDescriptorCommandParameterState.h @@ -31,7 +31,7 @@ class WaitFaceDescriptorCommandParameterState : public SoundFaceFollowingState WaitFaceDescriptorCommandParameterState( StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, float noseConfidenceThreshold); ~WaitFaceDescriptorCommandParameterState() override; @@ -41,11 +41,11 @@ class WaitFaceDescriptorCommandParameterState : public SoundFaceFollowingState void onEnabling(const StateParameter& parameter, const StateType& previousStateType) override; void onDisabling() override; - void onVideoAnalysisReceived(const video_analyzer::VideoAnalysis::ConstPtr& msg) override; + void onVideoAnalysisReceived(const perception_msgs::msg::VideoAnalysis::SharedPtr& msg) override; void onStateTimeout() override; private: - std::optional findNearestFaceDescriptor(const video_analyzer::VideoAnalysis::ConstPtr& msg); + std::optional findNearestFaceDescriptor(const perception_msgs::msg::VideoAnalysis::SharedPtr& msg); void switchState(); }; diff --git a/ros/demos/home_logger/test/home_logger_common/PropertiesTests.cpp b/ros/demos/home_logger/test/home_logger_common/PropertiesTests.cpp index 32e43429..2c16a995 100644 --- a/ros/demos/home_logger/test/home_logger_common/PropertiesTests.cpp +++ b/ros/demos/home_logger/test/home_logger_common/PropertiesTests.cpp @@ -1,11 +1,11 @@ #include -#include +#include #include using namespace std; -namespace fs = boost::filesystem; +namespace fs = std::filesystem; TEST(PropertiesTests, constructor_map_shouldCopyTheMap) { diff --git a/ros/demos/home_logger/test/home_logger_common/language/StringResourcesTests.cpp b/ros/demos/home_logger/test/home_logger_common/language/StringResourcesTests.cpp index 23dd0c69..63e20f56 100644 --- a/ros/demos/home_logger/test/home_logger_common/language/StringResourcesTests.cpp +++ b/ros/demos/home_logger/test/home_logger_common/language/StringResourcesTests.cpp @@ -1,11 +1,11 @@ #include -#include +#include #include using namespace std; -namespace fs = boost::filesystem; +namespace fs = std::filesystem; TEST(StringResourcesTests, getValue_notInitialized_shouldThrowRuntimeError) { diff --git a/ros/demos/home_logger/test/home_logger_common/loadStringResources.cpp b/ros/demos/home_logger/test/home_logger_common/loadStringResources.cpp index d9b89f15..34eb296c 100644 --- a/ros/demos/home_logger/test/home_logger_common/loadStringResources.cpp +++ b/ros/demos/home_logger/test/home_logger_common/loadStringResources.cpp @@ -1,9 +1,9 @@ #include #include -#include +#include -namespace fs = boost::filesystem; +namespace fs = std::filesystem; void loadFrenchStringResources() { diff --git a/ros/demos/home_logger/test/home_logger_common/parameters/ReminderCommandParametersParsersTests.cpp b/ros/demos/home_logger/test/home_logger_common/parameters/ReminderCommandParametersParsersTests.cpp index 86a2ff5c..a920aa89 100644 --- a/ros/demos/home_logger/test/home_logger_common/parameters/ReminderCommandParametersParsersTests.cpp +++ b/ros/demos/home_logger/test/home_logger_common/parameters/ReminderCommandParametersParsersTests.cpp @@ -82,8 +82,7 @@ TEST(AddReminderCommandParametersParserTests, parse_faceDescriptor_shouldReturnA loadFrenchStringResources(); AddReminderCommandParametersParser testee; - auto command = - testee.parse(make_shared("a"), nullopt, nullopt, FaceDescriptor({11.f})); + auto command = testee.parse(make_shared("a"), nullopt, nullopt, FaceDescriptor({11.f})); auto addReminderCommand = dynamic_pointer_cast(command); EXPECT_EQ(addReminderCommand->transcript(), "a"); EXPECT_EQ(addReminderCommand->text(), nullopt); @@ -129,8 +128,7 @@ TEST(RemoveReminderCommandParametersParserTests, parse_parameterNothing_shouldRe TEST(RemoveReminderCommandParametersParserTests, parse_transcriptCurrent_shouldReturnACopyWithVolume) { RemoveReminderCommandParametersParser testee; - auto command = - testee.parse(make_shared("Alarme 15"), nullopt, nullopt, nullopt); + auto command = testee.parse(make_shared("Alarme 15"), nullopt, nullopt, nullopt); auto removeReminderCommand = dynamic_pointer_cast(command); EXPECT_EQ(removeReminderCommand->transcript(), "Alarme 15"); EXPECT_EQ(removeReminderCommand->id(), 15); diff --git a/ros/demos/smart_speaker/CMakeLists.txt b/ros/demos/smart_speaker/CMakeLists.txt index 54de5462..4ce9fb0d 100644 --- a/ros/demos/smart_speaker/CMakeLists.txt +++ b/ros/demos/smart_speaker/CMakeLists.txt @@ -1,152 +1,31 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(smart_speaker) -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - audio_analyzer - cloud_data - gesture - hbba_lite - person_identification - rospy - roscpp - sensor_msgs - std_msgs - talk - video_analyzer - t_top_hbba_lite - tf - speech_to_text - sound_player - led_animations - daemon_ros_client -) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -# add_message_files( -# FILES -# Message1.msg -# Message2.msg -# ) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -# generate_messages( -# DEPENDENCIES -# sensor_msgs# std_msgs -# ) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( - # INCLUDE_DIRS include - # LIBRARIES smart_speaker - # CATKIN_DEPENDS audio_analyzer cloud_data gesture hbba_lite person_identification roscpp sensor_msgs std_msgs talk video_analyzer - # DEPENDS system_lib -) - -########### -## Build ## -########### +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( - # include - ${catkin_INCLUDE_DIRS} -) +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/smart_speaker.cpp -# ) +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclcpp REQUIRED) +find_package(cloud_data REQUIRED) +find_package(t_top_hbba_lite REQUIRED) +find_package(tf2 REQUIRED) +find_package(tf2_ros REQUIRED) +find_package(tf2_geometry_msgs REQUIRED) +find_package(perception_msgs REQUIRED) -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide add_executable(${PROJECT_NAME}_rss_node src/${PROJECT_NAME}_rss_node.cpp src/StringUtils.cpp @@ -168,6 +47,16 @@ add_executable(${PROJECT_NAME}_rss_node src/states/rss/RssValidTaskState.cpp src/states/rss/RssStoryState.cpp ) +ament_target_dependencies(${PROJECT_NAME}_rss_node + rclcpp + cloud_data + t_top_hbba_lite + tf2 + tf2_ros + tf2_geometry_msgs + perception_msgs +) +install(TARGETS ${PROJECT_NAME}_rss_node DESTINATION lib/${PROJECT_NAME}) add_executable(${PROJECT_NAME}_smart_node src/${PROJECT_NAME}_smart_node.cpp @@ -188,77 +77,21 @@ add_executable(${PROJECT_NAME}_smart_node src/states/smart/SmartAskOtherTaskState.cpp src/states/smart/SmartThankYouState.cpp ) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -target_link_libraries(${PROJECT_NAME}_rss_node - ${catkin_LIBRARIES} -) - -target_link_libraries(${PROJECT_NAME}_smart_node - ${catkin_LIBRARIES} +ament_target_dependencies(${PROJECT_NAME}_smart_node + rclcpp + cloud_data + t_top_hbba_lite + tf2 + tf2_ros + tf2_geometry_msgs + perception_msgs ) +install(TARGETS ${PROJECT_NAME}_smart_node DESTINATION lib/${PROJECT_NAME}) -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -# catkin_install_python(PROGRAMS -# scripts/script.py -# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# +# Launch files +install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}) -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_smart_speaker.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() +# Resources files +install(DIRECTORY resources DESTINATION share/${PROJECT_NAME}) -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/demos/smart_speaker/launch/smart_speaker_rss.launch b/ros/demos/smart_speaker/launch/smart_speaker_rss.launch deleted file mode 100644 index 3f643a5f..00000000 --- a/ros/demos/smart_speaker/launch/smart_speaker_rss.launch +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/ros/demos/smart_speaker/launch/smart_speaker_rss.launch.xml b/ros/demos/smart_speaker/launch/smart_speaker_rss.launch.xml new file mode 100644 index 00000000..79008e18 --- /dev/null +++ b/ros/demos/smart_speaker/launch/smart_speaker_rss.launch.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/ros/demos/smart_speaker/launch/smart_speaker_smart.launch b/ros/demos/smart_speaker/launch/smart_speaker_smart.launch deleted file mode 100644 index 24ead048..00000000 --- a/ros/demos/smart_speaker/launch/smart_speaker_smart.launch +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - name: Ça fait rire les oiseaux - keywords: - - rire - - oiseau - path: ~/.ros/ttop/audio/fr/Compagnie_créole_ca_fait_rire_les_oiseaux_30s.mp3 - - name: La dame en bleu, - keywords: - - dame - - bleu - path: ~/.ros/ttop/audio/fr/Michel_Louvain_La_Dame_En_Bleu_30s.mp3 - - name: Un amour qui ne veut pas mourir, - keywords: - - amour - - mourir - path: ~/.ros/ttop/audio/fr/Renee_Martel_Un_Amour_Qui_Ne_Veut_Pas_Mourir_30s.mp3 - - - - name: Can't Buy Me Love - keywords: - - buy - - love - path: ~/.ros/ttop/audio/en/The_Beatles_Cant_Buy_Me_Love_30s.mp3 - - name: Surfin' USA - keywords: - - surf - - usa - path: ~/.ros/ttop/audio/en/The_Beach_Boys_Surfin_USA_30s.mp3 - - name: The Locomotion - keywords: - - locomotion - path: ~/.ros/ttop/audio/en/Little_Eva_The_Locomotion_30s.mp3 - - - - - - - - - - - - - diff --git a/ros/demos/smart_speaker/launch/smart_speaker_smart.launch.xml b/ros/demos/smart_speaker/launch/smart_speaker_smart.launch.xml new file mode 100644 index 00000000..703bd993 --- /dev/null +++ b/ros/demos/smart_speaker/launch/smart_speaker_smart.launch.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ros/demos/smart_speaker/package.xml b/ros/demos/smart_speaker/package.xml index fbe3b6f0..f39cc496 100644 --- a/ros/demos/smart_speaker/package.xml +++ b/ros/demos/smart_speaker/package.xml @@ -1,107 +1,29 @@ - + + smart_speaker 0.0.0 The smart_speaker package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rclcpp + cloud_data + t_top_hbba_lite + tf2 + tf2_ros + tf2_geometry_msgs + perception_msgs - - - - TODO + rosidl_default_runtime + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - audio_analyzer - cloud_data - gesture - hbba_lite - person_identification - roscpp - sensor_msgs - std_msgs - talk - video_analyzer - t_top_hbba_lite - tf - speech_to_text - sound_player - led_animations - daemon_ros_client - audio_analyzer - cloud_data - gesture - hbba_lite - person_identification - roscpp - sensor_msgs - std_msgs - talk - video_analyzer - t_top_hbba_lite - tf - speech_to_text - sound_player - led_animations - daemon_ros_client - audio_analyzer - cloud_data - gesture - hbba_lite - person_identification - roscpp - sensor_msgs - std_msgs - talk - video_analyzer - t_top_hbba_lite - tf - speech_to_text - sound_player - led_animations - daemon_ros_client - - - - - + ament_cmake diff --git a/ros/demos/smart_speaker/admiralbob_wanderer.mp3 b/ros/demos/smart_speaker/resources/admiralbob_wanderer.mp3 similarity index 100% rename from ros/demos/smart_speaker/admiralbob_wanderer.mp3 rename to ros/demos/smart_speaker/resources/admiralbob_wanderer.mp3 diff --git a/ros/demos/smart_speaker/story_en.txt b/ros/demos/smart_speaker/resources/story_en.txt similarity index 100% rename from ros/demos/smart_speaker/story_en.txt rename to ros/demos/smart_speaker/resources/story_en.txt diff --git a/ros/demos/smart_speaker/story_fr.txt b/ros/demos/smart_speaker/resources/story_fr.txt similarity index 100% rename from ros/demos/smart_speaker/story_fr.txt rename to ros/demos/smart_speaker/resources/story_fr.txt diff --git a/ros/demos/smart_speaker/src/smart_speaker_rss_node.cpp b/ros/demos/smart_speaker/src/smart_speaker_rss_node.cpp index 357cf847..56834911 100644 --- a/ros/demos/smart_speaker/src/smart_speaker_rss_node.cpp +++ b/ros/demos/smart_speaker/src/smart_speaker_rss_node.cpp @@ -15,7 +15,7 @@ #include "states/common/AfterTaskDelayState.h" -#include +#include #include #include @@ -30,18 +30,19 @@ using namespace std; constexpr bool WAIT_FOR_SERVICE = true; +constexpr const char* NODE_NAME = "smart_speaker_rss_node"; void startNode( Language language, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, const string& englishStoryPath, const string& frenchStoryPath, const string& songPath, bool useAfterTaskDelayDurationTopic, - const ros::Duration& afterTaskDelayDuration) + const chrono::milliseconds& afterTaskDelayDurationMs) { auto desireSet = make_shared(); - auto filterPool = make_shared(nodeHandle, WAIT_FOR_SERVICE); + auto filterPool = make_shared(node, WAIT_FOR_SERVICE); vector> strategies; strategies.emplace_back(createRobotNameDetectorStrategy(filterPool)); @@ -51,42 +52,41 @@ void startNode( strategies.emplace_back(createSpeechToTextStrategy(filterPool)); strategies.emplace_back(createExploreStrategy(filterPool)); - strategies.emplace_back(createFaceAnimationStrategy(filterPool, nodeHandle)); + strategies.emplace_back(createFaceAnimationStrategy(filterPool, node)); strategies.emplace_back(createSoundFollowingStrategy(filterPool)); strategies.emplace_back(createNearestFaceFollowingStrategy(filterPool)); - strategies.emplace_back(createTalkStrategy(filterPool, desireSet, nodeHandle)); - strategies.emplace_back(createGestureStrategy(filterPool, desireSet, nodeHandle)); + strategies.emplace_back(createTalkStrategy(filterPool, desireSet, node)); + strategies.emplace_back(createGestureStrategy(filterPool, desireSet, node)); strategies.emplace_back(createDanceStrategy(filterPool)); - strategies.emplace_back(createPlaySoundStrategy(filterPool, desireSet, nodeHandle)); + strategies.emplace_back(createPlaySoundStrategy(filterPool, desireSet, node)); auto solver = make_unique(); - auto strategyStateLogger = make_unique(nodeHandle); + auto strategyStateLogger = make_unique(node); HbbaLite hbba(desireSet, move(strategies), {{"sound", 1}}, move(solver), move(strategyStateLogger)); - StateManager stateManager; + StateManager stateManager(node); type_index idleStateType(typeid(RssIdleState)); type_index afterTaskDelayStateType(typeid(AfterTaskDelayState)); - stateManager.addState(make_unique(language, stateManager, desireSet, nodeHandle)); - stateManager.addState(make_unique(language, stateManager, desireSet, nodeHandle)); - stateManager.addState(make_unique(language, stateManager, desireSet, nodeHandle)); - stateManager.addState(make_unique(language, stateManager, desireSet, nodeHandle)); - stateManager.addState(make_unique(language, stateManager, desireSet, nodeHandle)); - stateManager.addState(make_unique(language, stateManager, desireSet, nodeHandle, idleStateType)); + stateManager.addState(make_unique(language, stateManager, desireSet, node)); + stateManager.addState(make_unique(language, stateManager, desireSet, node)); + stateManager.addState(make_unique(language, stateManager, desireSet, node)); + stateManager.addState(make_unique(language, stateManager, desireSet, node)); + stateManager.addState(make_unique(language, stateManager, desireSet, node)); + stateManager.addState(make_unique(language, stateManager, desireSet, node, idleStateType)); stateManager.addState( - make_unique(language, stateManager, desireSet, nodeHandle, afterTaskDelayStateType)); + make_unique(language, stateManager, desireSet, node, afterTaskDelayStateType)); stateManager.addState( - make_unique(language, stateManager, desireSet, nodeHandle, afterTaskDelayStateType)); + make_unique(language, stateManager, desireSet, node, afterTaskDelayStateType)); stateManager.addState( - make_unique(language, stateManager, desireSet, nodeHandle, englishStoryPath, frenchStoryPath)); - stateManager.addState( - make_unique(language, stateManager, desireSet, nodeHandle, afterTaskDelayStateType)); + make_unique(language, stateManager, desireSet, node, englishStoryPath, frenchStoryPath)); + stateManager.addState(make_unique(language, stateManager, desireSet, node, afterTaskDelayStateType)); stateManager.addState(make_unique( language, stateManager, desireSet, - nodeHandle, + node, afterTaskDelayStateType, vector{songPath})); @@ -94,83 +94,80 @@ void startNode( language, stateManager, desireSet, - nodeHandle, + node, idleStateType, useAfterTaskDelayDurationTopic, - afterTaskDelayDuration)); + afterTaskDelayDurationMs)); stateManager.switchTo(); - ros::spin(); + rclcpp::executors::MultiThreadedExecutor executor(rclcpp::ExecutorOptions(), 2); + executor.add_node(node); + executor.spin(); } -int startNode(int argc, char** argv) +int startNode() { - ros::init(argc, argv, "smart_speaker_rss_node"); - ros::NodeHandle nodeHandle; - ros::NodeHandle privateNodeHandle("~"); + auto node = rclcpp::Node::make_shared(NODE_NAME); - string languageString; + string languageString = node->declare_parameter("language", ""); Language language; - privateNodeHandle.param("language", languageString, ""); if (!languageFromString(languageString, language)) { - ROS_ERROR("Language must be English (language=en) or French (language=fr)."); + RCLCPP_ERROR(node->get_logger(), "Language must be English (language=en) or French (language=fr)."); return -1; } - string englishStoryPath; - privateNodeHandle.param("story_path_en", englishStoryPath, ""); + string englishStoryPath = node->declare_parameter("story_path_en", ""); if (englishStoryPath == "") { - ROS_ERROR("A valid path must be set for the English story."); + RCLCPP_ERROR(node->get_logger(), "A valid path must be set for the English story."); return -1; } - string frenchStoryPath; - privateNodeHandle.param("story_path_fr", frenchStoryPath, ""); + string frenchStoryPath = node->declare_parameter("story_path_fr", ""); if (frenchStoryPath == "") { - ROS_ERROR("A valid path must be set for the French story."); + RCLCPP_ERROR(node->get_logger(), "A valid path must be set for the French story."); return -1; } - string songPath; - privateNodeHandle.param("song_path", songPath, ""); + string songPath = node->declare_parameter("song_path", ""); if (songPath == "") { - ROS_ERROR("A valid path must be set for the song."); + RCLCPP_ERROR(node->get_logger(), "A valid path must be set for the song."); return -1; } - bool useAfterTaskDelayDurationTopic = false; - privateNodeHandle.param("use_after_task_delay_duration_topic", useAfterTaskDelayDurationTopic, false); - - double afterTaskDelayDurationS; - privateNodeHandle.param("after_task_delay_duration_s", afterTaskDelayDurationS, 0.0); - ros::Duration afterTaskDelayDuration(afterTaskDelayDurationS); + bool useAfterTaskDelayDurationTopic = node->declare_parameter("use_after_task_delay_duration_topic", false); + double afterTaskDelayDurationS = node->declare_parameter("after_task_delay_duration_s", 0.0); + chrono::milliseconds afterTaskDelayDurationMs(static_cast(afterTaskDelayDurationS * 1000)); startNode( language, - nodeHandle, + node, englishStoryPath, frenchStoryPath, songPath, useAfterTaskDelayDurationTopic, - afterTaskDelayDuration); + afterTaskDelayDurationMs); return 0; } int main(int argc, char** argv) { + rclcpp::init(argc, argv); + try { - return startNode(argc, argv); + return startNode(); } catch (const std::exception& e) { - ROS_ERROR_STREAM("Smart speaker crashed (" << e.what() << ")"); + RCLCPP_ERROR_STREAM(rclcpp::get_logger(NODE_NAME), "Smart speaker crashed (" << e.what() << ")"); return -1; } + + rclcpp::shutdown(); } diff --git a/ros/demos/smart_speaker/src/smart_speaker_smart_node.cpp b/ros/demos/smart_speaker/src/smart_speaker_smart_node.cpp index 67a9ecb4..62bb9db9 100644 --- a/ros/demos/smart_speaker/src/smart_speaker_smart_node.cpp +++ b/ros/demos/smart_speaker/src/smart_speaker_smart_node.cpp @@ -1,3 +1,5 @@ +#include "StringUtils.h" + #include "states/StateManager.h" #include "states/smart/SmartIdleState.h" @@ -13,7 +15,7 @@ #include "states/smart/SmartThankYouState.h" #include "states/common/AfterTaskDelayState.h" -#include +#include #include #include @@ -28,11 +30,27 @@ using namespace std; constexpr bool WAIT_FOR_SERVICE = true; +constexpr const char* NODE_NAME = "smart_speaker_smart_node"; + +void logSongs( + rclcpp::Node::SharedPtr& node, + const vector& songNames, + const vector>& songKeywords, + const vector& songPaths) +{ + for (size_t i = 0; i < songNames.size(); i++) + { + RCLCPP_INFO_STREAM(node->get_logger(), "Song " << (i + 1)); + RCLCPP_INFO_STREAM(node->get_logger(), "\tname=" << songNames[i]); + RCLCPP_INFO_STREAM(node->get_logger(), "\tkeywords=" << mergeStrings(songKeywords[i], ",")); + RCLCPP_INFO_STREAM(node->get_logger(), "\tpath=" << songPaths[i]); + } +} void startNode( bool recordSession, Language language, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, double personDistanceThreshold, const std::string& personDistanceFrameId, double noseConfidenceThreshold, @@ -43,10 +61,10 @@ void startNode( const vector& songPaths, bool singleTaskPerPerson, bool useAfterTaskDelayDurationTopic, - const ros::Duration& afterTaskDelayDuration) + const chrono::milliseconds& afterTaskDelayDurationMs) { auto desireSet = make_shared(); - auto filterPool = make_shared(nodeHandle, WAIT_FOR_SERVICE); + auto filterPool = make_shared(node, WAIT_FOR_SERVICE); vector> strategies; strategies.emplace_back(createCamera3dRecordingStrategy(filterPool)); @@ -54,58 +72,52 @@ void startNode( strategies.emplace_back(createFastVideoAnalyzer3dStrategy(filterPool)); strategies.emplace_back(createSpeechToTextStrategy(filterPool)); - strategies.emplace_back(createFaceAnimationStrategy(filterPool, nodeHandle)); + strategies.emplace_back(createFaceAnimationStrategy(filterPool, node)); strategies.emplace_back(createNearestFaceFollowingStrategy(filterPool)); - strategies.emplace_back(createTalkStrategy(filterPool, desireSet, nodeHandle)); - strategies.emplace_back(createGestureStrategy(filterPool, desireSet, nodeHandle)); + strategies.emplace_back(createTalkStrategy(filterPool, desireSet, node)); + strategies.emplace_back(createGestureStrategy(filterPool, desireSet, node)); strategies.emplace_back(createDanceStrategy(filterPool)); - strategies.emplace_back(createPlaySoundStrategy(filterPool, desireSet, nodeHandle)); + strategies.emplace_back(createPlaySoundStrategy(filterPool, desireSet, node)); auto solver = make_unique(); - auto strategyStateLogger = make_unique(nodeHandle); + auto strategyStateLogger = make_unique(node); HbbaLite hbba(desireSet, move(strategies), {{"sound", 1}}, move(solver), move(strategyStateLogger)); - StateManager stateManager; + StateManager stateManager(node); type_index askOtherTaskStateType(typeid(SmartAskOtherTaskState)); stateManager.addState(make_unique( language, stateManager, desireSet, - nodeHandle, + node, personDistanceThreshold, personDistanceFrameId, noseConfidenceThreshold, videoAnalysisMessageCountThreshold, videoAnalysisMessageCountTolerance)); - stateManager.addState(make_unique(language, stateManager, desireSet, nodeHandle, songNames)); - stateManager.addState( - make_unique(language, stateManager, desireSet, nodeHandle, songKeywords)); - stateManager.addState(make_unique(language, stateManager, desireSet, nodeHandle)); + stateManager.addState(make_unique(language, stateManager, desireSet, node, songNames)); + stateManager.addState(make_unique(language, stateManager, desireSet, node, songKeywords)); + stateManager.addState(make_unique(language, stateManager, desireSet, node)); stateManager.addState( - make_unique(language, stateManager, desireSet, nodeHandle, askOtherTaskStateType)); + make_unique(language, stateManager, desireSet, node, askOtherTaskStateType)); stateManager.addState( - make_unique(language, stateManager, desireSet, nodeHandle, askOtherTaskStateType)); - stateManager.addState(make_unique( - language, - stateManager, - desireSet, - nodeHandle, - askOtherTaskStateType, - songPaths)); + make_unique(language, stateManager, desireSet, node, askOtherTaskStateType)); + stateManager.addState( + make_unique(language, stateManager, desireSet, node, askOtherTaskStateType, songPaths)); stateManager.addState( - make_unique(language, stateManager, desireSet, nodeHandle, singleTaskPerPerson)); - stateManager.addState(make_unique(language, stateManager, desireSet, nodeHandle)); + make_unique(language, stateManager, desireSet, node, singleTaskPerPerson)); + stateManager.addState(make_unique(language, stateManager, desireSet, node)); stateManager.addState(make_unique( language, stateManager, desireSet, - nodeHandle, + node, typeid(SmartIdleState), useAfterTaskDelayDurationTopic, - afterTaskDelayDuration)); + afterTaskDelayDurationMs)); stateManager.switchTo(); @@ -114,175 +126,123 @@ void startNode( desireSet->addDesire(make_unique()); } - ros::spin(); -} - -bool getSongStrings(ros::NodeHandle& privateNodeHandle, vector& values, const std::string& key) -{ - string value; - - XmlRpc::XmlRpcValue songs; - privateNodeHandle.getParam("songs", songs); - if (songs.getType() != XmlRpc::XmlRpcValue::TypeArray) - { - ROS_ERROR("Invalid songs format"); - return false; - } - - for (size_t i = 0; i < songs.size(); i++) - { - if (!songs[i].hasMember(key) || (value = static_cast(songs[i][key])).empty()) - { - ROS_ERROR_STREAM("Invalid songs[" << i << "] " << key); - return false; - } - - values.emplace_back(move(value)); - } - - return values.size() > 0; + rclcpp::executors::MultiThreadedExecutor executor(rclcpp::ExecutorOptions(), 2); + executor.add_node(node); + executor.spin(); } -bool getSongVectors(ros::NodeHandle& privateNodeHandle, vector>& values, const std::string& key) +int startNode() { - vector value; + auto node = rclcpp::Node::make_shared(NODE_NAME); - XmlRpc::XmlRpcValue songs; - privateNodeHandle.getParam("songs", songs); - if (songs.getType() != XmlRpc::XmlRpcValue::TypeArray) - { - ROS_ERROR("Invalid songs format"); - return false; - } + bool recordSession = node->declare_parameter("record_session", false); - for (size_t i = 0; i < songs.size(); i++) - { - if (!songs[i].hasMember(key) || songs[i][key].getType() != XmlRpc::XmlRpcValue::TypeArray) - { - ROS_ERROR_STREAM("Invalid songs[" << i << "] " << key); - return false; - } - - for (size_t j = 0; j < songs[i][key].size(); j++) - { - value.emplace_back(songs[i][key][j]); - } - - values.emplace_back(move(value)); - } - - return values.size() > 0; -} - -int startNode(int argc, char** argv) -{ - ros::init(argc, argv, "smart_speaker_smart_node"); - ros::NodeHandle nodeHandle; - ros::NodeHandle privateNodeHandle("~"); - - bool recordSession; - if (!privateNodeHandle.getParam("record_session", recordSession)) - { - ROS_ERROR("The parameter record_session must be set."); - return -1; - } - - string languageString; + string languageString = node->declare_parameter("language", ""); Language language; - privateNodeHandle.param("language", languageString, ""); if (!languageFromString(languageString, language)) { - ROS_ERROR("Language must be English (language=en) or French (language=fr)."); + RCLCPP_ERROR(node->get_logger(), "Language must be English (language=en) or French (language=fr)."); return -1; } - double personDistanceThreshold = -1.0; - if (!privateNodeHandle.getParam("person_distance_threshold", personDistanceThreshold) || - personDistanceThreshold < 0.0) + double personDistanceThreshold = node->declare_parameter("person_distance_threshold", -1.0); + if (personDistanceThreshold < 0.0) { - ROS_ERROR("The parameter person_distance_threshold must be set and greater than 0."); + RCLCPP_ERROR(node->get_logger(), "The parameter person_distance_threshold must be set and greater than 0."); return -1; } - std::string personDistanceFrameId; - if (!privateNodeHandle.getParam("person_distance_frame_id", personDistanceFrameId) || personDistanceFrameId == "") + std::string personDistanceFrameId = node->declare_parameter("person_distance_frame_id", ""); + if (personDistanceFrameId == "") { - ROS_ERROR("The parameter person_distance_frame_id must be set and not empty."); + RCLCPP_ERROR(node->get_logger(), "The parameter person_distance_frame_id must be set and not empty."); return -1; } - double noseConfidenceThreshold = -1.0; - if (!privateNodeHandle.getParam("nose_confidence_threshold", noseConfidenceThreshold) || - noseConfidenceThreshold < 0.0) + double noseConfidenceThreshold = node->declare_parameter("nose_confidence_threshold", -1.0); + if (noseConfidenceThreshold < 0.0) { - ROS_ERROR("The parameter nose_confidence_threshold must be set and not empty."); + RCLCPP_ERROR(node->get_logger(), "The parameter nose_confidence_threshold must be set and not empty."); return -1; } - int videoAnalysisMessageCountThreshold = -1; - if (!privateNodeHandle.getParam("video_analysis_message_count_threshold", videoAnalysisMessageCountThreshold) || - videoAnalysisMessageCountThreshold < 1) + int videoAnalysisMessageCountThreshold = node->declare_parameter("video_analysis_message_count_threshold", -1); + if (videoAnalysisMessageCountThreshold < 1) { - ROS_ERROR("The parameter video_analysis_message_count_threshold must be set and greater than 0."); + RCLCPP_ERROR( + node->get_logger(), + "The parameter video_analysis_message_count_threshold must be set and greater than 0."); return -1; } - int videoAnalysisMessageCountTolerance = -1; - if (!privateNodeHandle.getParam("video_analysis_message_count_tolerance", videoAnalysisMessageCountTolerance) || - videoAnalysisMessageCountTolerance < 0) + int videoAnalysisMessageCountTolerance = node->declare_parameter("video_analysis_message_count_tolerance", -1); + if (videoAnalysisMessageCountTolerance < 0) { - ROS_ERROR("The parameter video_analysis_message_count_tolerance must be set and greater than or equal to 0."); + RCLCPP_ERROR( + node->get_logger(), + "The parameter video_analysis_message_count_tolerance must be set and greater than or equal to 0."); return -1; } - bool singleTaskPerPerson = false; - privateNodeHandle.param("single_task_per_person", singleTaskPerPerson, false); + bool singleTaskPerPerson = node->declare_parameter("single_task_per_person", false); + bool useAfterTaskDelayDurationTopic = node->declare_parameter("use_after_task_delay_duration_topic", false); - bool useAfterTaskDelayDurationTopic = false; - privateNodeHandle.param("use_after_task_delay_duration_topic", useAfterTaskDelayDurationTopic, false); + double afterTaskDelayDurationS = node->declare_parameter("after_task_delay_duration_s", 0.0); + chrono::milliseconds afterTaskDelayDurationMs(static_cast(afterTaskDelayDurationS * 1000)); - double afterTaskDelayDurationS; - privateNodeHandle.param("after_task_delay_duration_s", afterTaskDelayDurationS, 0.0); - ros::Duration afterTaskDelayDuration(afterTaskDelayDurationS); - - vector songNames; - vector> songKeywords; - vector songPaths; - if (!getSongStrings(privateNodeHandle, songNames, "name") || - !getSongVectors(privateNodeHandle, songKeywords, "keywords") || - !getSongStrings(privateNodeHandle, songPaths, "path")) + vector songNames = node->declare_parameter("song_names", vector{}); + vector songKeywords = node->declare_parameter("song_keywords", vector{}); + vector songPaths = node->declare_parameter("song_paths", vector{}); + if (songNames.size() != songKeywords.size() || songNames.size() != songPaths.size() || songNames.size() < 1) { + RCLCPP_ERROR( + node->get_logger(), + "The parameters song_names, song_keywords and song_paths must have the same size and contain at least one " + "item."); return -1; } + vector> splittedSongKeywords; + std::transform( + songKeywords.begin(), + songKeywords.end(), + std::back_inserter(splittedSongKeywords), + [](auto& x) { return splitStrings(x, ";"); }); + + + logSongs(node, songNames, splittedSongKeywords, songPaths); startNode( recordSession, language, - nodeHandle, + node, personDistanceThreshold, personDistanceFrameId, noseConfidenceThreshold, videoAnalysisMessageCountThreshold, videoAnalysisMessageCountTolerance, songNames, - songKeywords, + splittedSongKeywords, songPaths, singleTaskPerPerson, useAfterTaskDelayDurationTopic, - afterTaskDelayDuration); + afterTaskDelayDurationMs); return 0; } int main(int argc, char** argv) { + rclcpp::init(argc, argv); + try { - return startNode(argc, argv); + return startNode(); } catch (const std::exception& e) { - ROS_ERROR_STREAM("Smart speaker crashed (" << e.what() << ")"); + RCLCPP_ERROR_STREAM(rclcpp::get_logger(NODE_NAME), "Smart speaker crashed (" << e.what() << ")"); return -1; } + + rclcpp::shutdown(); } diff --git a/ros/demos/smart_speaker/src/states/State.cpp b/ros/demos/smart_speaker/src/states/State.cpp index a28b8b15..00e8aab4 100644 --- a/ros/demos/smart_speaker/src/states/State.cpp +++ b/ros/demos/smart_speaker/src/states/State.cpp @@ -6,12 +6,12 @@ State::State( Language language, StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle) + rclcpp::Node::SharedPtr node) : m_enabled(false), m_language(language), m_stateManager(stateManager), m_desireSet(move(desireSet)), - m_nodeHandle(nodeHandle), + m_node(move(node)), m_previousStageType(typeid(State)) { } diff --git a/ros/demos/smart_speaker/src/states/State.h b/ros/demos/smart_speaker/src/states/State.h index c125c170..e2c6790b 100644 --- a/ros/demos/smart_speaker/src/states/State.h +++ b/ros/demos/smart_speaker/src/states/State.h @@ -4,14 +4,14 @@ #include #include -#include +#include #include #include #include #include -constexpr double TIMEOUT_S = 30; +constexpr int TIMEOUT_S = 30; constexpr uint64_t MAX_DESIRE_ID = std::numeric_limits::max(); // TODO change to optional with C++17 constexpr int FLOAT_NUMBER_PRECISION = 3; @@ -50,7 +50,7 @@ class State protected: StateManager& m_stateManager; std::shared_ptr m_desireSet; - ros::NodeHandle& m_nodeHandle; + rclcpp::Node::SharedPtr m_node; std::vector m_desireIds; @@ -59,7 +59,7 @@ class State Language language, StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle); + rclcpp::Node::SharedPtr node); virtual ~State() = default; DECLARE_NOT_COPYABLE(State); diff --git a/ros/demos/smart_speaker/src/states/StateManager.cpp b/ros/demos/smart_speaker/src/states/StateManager.cpp index 61ae9aa7..7d56ea0c 100644 --- a/ros/demos/smart_speaker/src/states/StateManager.cpp +++ b/ros/demos/smart_speaker/src/states/StateManager.cpp @@ -2,7 +2,7 @@ using namespace std; -StateManager::StateManager() : m_currentState(nullptr) {} +StateManager::StateManager(rclcpp::Node::SharedPtr node) : m_currentState(nullptr), m_node(move(node)) {} StateManager::~StateManager() { diff --git a/ros/demos/smart_speaker/src/states/StateManager.h b/ros/demos/smart_speaker/src/states/StateManager.h index 66110cbb..4c0b80ac 100644 --- a/ros/demos/smart_speaker/src/states/StateManager.h +++ b/ros/demos/smart_speaker/src/states/StateManager.h @@ -3,7 +3,7 @@ #include "State.h" -#include +#include #include @@ -15,8 +15,10 @@ class StateManager std::unordered_map> m_states; State* m_currentState; + rclcpp::Node::SharedPtr m_node; + public: - StateManager(); + StateManager(rclcpp::Node::SharedPtr node); virtual ~StateManager(); DECLARE_NOT_COPYABLE(StateManager); @@ -40,12 +42,12 @@ inline void StateManager::switchTo(std::type_index stateType, const std::string& std::type_index previousStageType(typeid(State)); if (m_currentState != nullptr) { - ROS_INFO("Disabling %s", m_currentState->type().name()); + RCLCPP_INFO(m_node->get_logger(), "Disabling %s", m_currentState->type().name()); m_currentState->disable(); previousStageType = m_currentState->type(); } - ROS_INFO("Enabling %s (%s)", stateType.name(), parameter.c_str()); + RCLCPP_INFO(m_node->get_logger(), "Enabling %s (%s)", stateType.name(), parameter.c_str()); m_currentState = m_states.at(stateType).get(); m_currentState->enable(parameter, previousStageType); } diff --git a/ros/demos/smart_speaker/src/states/common/AfterTaskDelayState.cpp b/ros/demos/smart_speaker/src/states/common/AfterTaskDelayState.cpp index fcf03358..31510423 100644 --- a/ros/demos/smart_speaker/src/states/common/AfterTaskDelayState.cpp +++ b/ros/demos/smart_speaker/src/states/common/AfterTaskDelayState.cpp @@ -8,19 +8,21 @@ AfterTaskDelayState::AfterTaskDelayState( Language language, StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, type_index nextStateType, bool useAfterTaskDelayDurationTopic, - ros::Duration duration) - : State(language, stateManager, desireSet, nodeHandle), + std::chrono::milliseconds durationMs) + : State(language, stateManager, desireSet, move(node)), m_nextStateType(nextStateType), m_useAfterTaskDelayDurationTopic(useAfterTaskDelayDurationTopic), - m_duration(duration) + m_durationMs(durationMs) { if (m_useAfterTaskDelayDurationTopic) { - m_readySubscriber = - nodeHandle.subscribe("after_task_delay_state_ready", 1, &AfterTaskDelayState::readyCallback, this); + m_startButtonSubscriber = m_node->create_subscription( + "daemon/start_button_pressed", + 1, + [this](const std_msgs::msg::Empty::SharedPtr msg) { startButtonCallback(msg); }); } } @@ -30,9 +32,7 @@ void AfterTaskDelayState::enable(const string& parameter, const type_index& prev if (!m_useAfterTaskDelayDurationTopic) { - constexpr bool oneshot = true; - m_timeoutTimer = - m_nodeHandle.createTimer(m_duration, &AfterTaskDelayState::timeoutTimerCallback, this, oneshot); + m_timeoutTimer = m_node->create_wall_timer(m_durationMs, [this]() { timeoutTimerCallback(); }); } } @@ -40,13 +40,14 @@ void AfterTaskDelayState::disable() { State::disable(); - if (m_timeoutTimer.isValid()) + if (m_timeoutTimer) { - m_timeoutTimer.stop(); + m_timeoutTimer->cancel(); + m_timeoutTimer = nullptr; } } -void AfterTaskDelayState::readyCallback(const std_msgs::Empty::ConstPtr& msg) +void AfterTaskDelayState::startButtonCallback(const std_msgs::msg::Empty::SharedPtr msg) { if (!enabled() || !m_useAfterTaskDelayDurationTopic) { @@ -56,7 +57,7 @@ void AfterTaskDelayState::readyCallback(const std_msgs::Empty::ConstPtr& msg) m_stateManager.switchTo(m_nextStateType); } -void AfterTaskDelayState::timeoutTimerCallback(const ros::TimerEvent& event) +void AfterTaskDelayState::timeoutTimerCallback() { if (!enabled()) { diff --git a/ros/demos/smart_speaker/src/states/common/AfterTaskDelayState.h b/ros/demos/smart_speaker/src/states/common/AfterTaskDelayState.h index f355c285..c2cba9f4 100644 --- a/ros/demos/smart_speaker/src/states/common/AfterTaskDelayState.h +++ b/ros/demos/smart_speaker/src/states/common/AfterTaskDelayState.h @@ -3,27 +3,27 @@ #include "../State.h" -#include +#include class AfterTaskDelayState : public State { std::type_index m_nextStateType; bool m_useAfterTaskDelayDurationTopic; - ros::Duration m_duration; + std::chrono::milliseconds m_durationMs; - ros::Subscriber m_readySubscriber; - ros::Timer m_timeoutTimer; + rclcpp::Subscription::SharedPtr m_startButtonSubscriber; + rclcpp::TimerBase::SharedPtr m_timeoutTimer; public: AfterTaskDelayState( Language language, StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, std::type_index nextStateType, bool useAfterTaskDelayDurationTopic, - ros::Duration duration); + std::chrono::milliseconds durationMs); ~AfterTaskDelayState() override = default; DECLARE_NOT_COPYABLE(AfterTaskDelayState); @@ -36,8 +36,8 @@ class AfterTaskDelayState : public State void disable() override; private: - void readyCallback(const std_msgs::Empty::ConstPtr& msg); - void timeoutTimerCallback(const ros::TimerEvent& event); + void startButtonCallback(const std_msgs::msg::Empty::SharedPtr msg); + void timeoutTimerCallback(); }; inline std::type_index AfterTaskDelayState::type() const diff --git a/ros/demos/smart_speaker/src/states/common/InvalidTaskState.cpp b/ros/demos/smart_speaker/src/states/common/InvalidTaskState.cpp index 625f83b5..a9769772 100644 --- a/ros/demos/smart_speaker/src/states/common/InvalidTaskState.cpp +++ b/ros/demos/smart_speaker/src/states/common/InvalidTaskState.cpp @@ -10,9 +10,9 @@ InvalidTaskState::InvalidTaskState( Language language, StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, type_index nextStateType) - : State(language, stateManager, desireSet, nodeHandle), + : State(language, stateManager, desireSet, move(node)), m_nextStateType(nextStateType), m_talkDesireId(MAX_DESIRE_ID), m_gestureDesireId(MAX_DESIRE_ID) diff --git a/ros/demos/smart_speaker/src/states/common/InvalidTaskState.h b/ros/demos/smart_speaker/src/states/common/InvalidTaskState.h index 050e0ceb..0f3043b0 100644 --- a/ros/demos/smart_speaker/src/states/common/InvalidTaskState.h +++ b/ros/demos/smart_speaker/src/states/common/InvalidTaskState.h @@ -15,7 +15,7 @@ class InvalidTaskState : public State, public DesireSetObserver Language language, StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, std::type_index nextStateType); ~InvalidTaskState() override; diff --git a/ros/demos/smart_speaker/src/states/common/TalkState.cpp b/ros/demos/smart_speaker/src/states/common/TalkState.cpp index e93e700b..970a9818 100644 --- a/ros/demos/smart_speaker/src/states/common/TalkState.cpp +++ b/ros/demos/smart_speaker/src/states/common/TalkState.cpp @@ -10,9 +10,9 @@ TalkState::TalkState( Language language, StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, type_index nextStateType) - : State(language, stateManager, desireSet, nodeHandle), + : State(language, stateManager, desireSet, move(node)), m_nextStateType(nextStateType), m_talkDesireId(MAX_DESIRE_ID) { diff --git a/ros/demos/smart_speaker/src/states/common/TalkState.h b/ros/demos/smart_speaker/src/states/common/TalkState.h index 08e7b215..9bcc9a2d 100644 --- a/ros/demos/smart_speaker/src/states/common/TalkState.h +++ b/ros/demos/smart_speaker/src/states/common/TalkState.h @@ -14,7 +14,7 @@ class TalkState : public State, public DesireSetObserver Language language, StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, std::type_index nextStateType); ~TalkState() override; diff --git a/ros/demos/smart_speaker/src/states/common/ValidTaskState.cpp b/ros/demos/smart_speaker/src/states/common/ValidTaskState.cpp index bbc2ddde..6064c46b 100644 --- a/ros/demos/smart_speaker/src/states/common/ValidTaskState.cpp +++ b/ros/demos/smart_speaker/src/states/common/ValidTaskState.cpp @@ -10,8 +10,8 @@ ValidTaskState::ValidTaskState( Language language, StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle) - : State(language, stateManager, desireSet, nodeHandle), + rclcpp::Node::SharedPtr node) + : State(language, stateManager, desireSet, move(node)), m_talkDesireId(MAX_DESIRE_ID), m_gestureDesireId(MAX_DESIRE_ID) { diff --git a/ros/demos/smart_speaker/src/states/common/ValidTaskState.h b/ros/demos/smart_speaker/src/states/common/ValidTaskState.h index a00db252..fdbf4e28 100644 --- a/ros/demos/smart_speaker/src/states/common/ValidTaskState.h +++ b/ros/demos/smart_speaker/src/states/common/ValidTaskState.h @@ -15,7 +15,7 @@ class ValidTaskState : public State, public DesireSetObserver Language language, StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle); + rclcpp::Node::SharedPtr node); ~ValidTaskState() override; DECLARE_NOT_COPYABLE(ValidTaskState); diff --git a/ros/demos/smart_speaker/src/states/common/WaitAnswerState.cpp b/ros/demos/smart_speaker/src/states/common/WaitAnswerState.cpp index 8d467fc1..4190e755 100644 --- a/ros/demos/smart_speaker/src/states/common/WaitAnswerState.cpp +++ b/ros/demos/smart_speaker/src/states/common/WaitAnswerState.cpp @@ -23,12 +23,14 @@ WaitAnswerState::WaitAnswerState( Language language, StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle) - : State(language, stateManager, desireSet, nodeHandle), + rclcpp::Node::SharedPtr node) + : State(language, stateManager, desireSet, move(node)), m_transcriptReceived(false) { - m_speechToTextSubscriber = - nodeHandle.subscribe("speech_to_text/transcript", 1, &WaitAnswerState::speechToTextSubscriberCallback, this); + m_speechToTextSubscriber = m_node->create_subscription( + "speech_to_text/transcript", + 1, + [this](const perception_msgs::msg::Transcript::SharedPtr msg) { speechToTextSubscriberCallback(msg); }); } void WaitAnswerState::enable(const string& parameter, const type_index& previousStageType) @@ -50,21 +52,21 @@ void WaitAnswerState::enable(const string& parameter, const type_index& previous m_desireSet->addDesire(move(faceAnimationDesire)); constexpr bool ONE_SHOT = true; - m_timeoutTimer = - m_nodeHandle.createTimer(ros::Duration(TIMEOUT_S), &WaitAnswerState::timeoutTimerCallback, this, ONE_SHOT); + m_timeoutTimer = m_node->create_wall_timer(chrono::seconds(TIMEOUT_S), [this]() { timeoutTimerCallback(); }); } void WaitAnswerState::disable() { State::disable(); - if (m_timeoutTimer.isValid()) + if (m_timeoutTimer) { - m_timeoutTimer.stop(); + m_timeoutTimer->cancel(); + m_timeoutTimer = nullptr; } } -void WaitAnswerState::speechToTextSubscriberCallback(const speech_to_text::Transcript::ConstPtr& msg) +void WaitAnswerState::speechToTextSubscriberCallback(const perception_msgs::msg::Transcript::SharedPtr msg) { if (!enabled()) { @@ -75,7 +77,7 @@ void WaitAnswerState::speechToTextSubscriberCallback(const speech_to_text::Trans switchStateAfterTranscriptReceived(msg->text, msg->is_final); } -void WaitAnswerState::timeoutTimerCallback(const ros::TimerEvent& event) +void WaitAnswerState::timeoutTimerCallback() { if (!enabled()) { diff --git a/ros/demos/smart_speaker/src/states/common/WaitAnswerState.h b/ros/demos/smart_speaker/src/states/common/WaitAnswerState.h index 7aa55c77..e25fa11c 100644 --- a/ros/demos/smart_speaker/src/states/common/WaitAnswerState.h +++ b/ros/demos/smart_speaker/src/states/common/WaitAnswerState.h @@ -3,12 +3,12 @@ #include "../State.h" -#include +#include class WaitAnswerState : public State { - ros::Subscriber m_speechToTextSubscriber; - ros::Timer m_timeoutTimer; + rclcpp::Subscription::SharedPtr m_speechToTextSubscriber; + rclcpp::TimerBase::SharedPtr m_timeoutTimer; bool m_transcriptReceived; @@ -17,7 +17,7 @@ class WaitAnswerState : public State Language language, StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle); + rclcpp::Node::SharedPtr node); ~WaitAnswerState() override = default; DECLARE_NOT_COPYABLE(WaitAnswerState); @@ -31,8 +31,8 @@ class WaitAnswerState : public State virtual void switchStateAfterTimeout(bool transcriptReceived) = 0; private: - void speechToTextSubscriberCallback(const speech_to_text::Transcript::ConstPtr& msg); - void timeoutTimerCallback(const ros::TimerEvent& event); + void speechToTextSubscriberCallback(const perception_msgs::msg::Transcript::SharedPtr msg); + void timeoutTimerCallback(); }; #endif diff --git a/ros/demos/smart_speaker/src/states/rss/RssAskTaskState.cpp b/ros/demos/smart_speaker/src/states/rss/RssAskTaskState.cpp index d5fb0b77..d74004a2 100644 --- a/ros/demos/smart_speaker/src/states/rss/RssAskTaskState.cpp +++ b/ros/demos/smart_speaker/src/states/rss/RssAskTaskState.cpp @@ -11,8 +11,8 @@ RssAskTaskState::RssAskTaskState( Language language, StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle) - : TalkState(language, stateManager, desireSet, nodeHandle, type_index(typeid(RssWaitAnswerState))) + rclcpp::Node::SharedPtr node) + : TalkState(language, stateManager, desireSet, move(node), type_index(typeid(RssWaitAnswerState))) { } diff --git a/ros/demos/smart_speaker/src/states/rss/RssAskTaskState.h b/ros/demos/smart_speaker/src/states/rss/RssAskTaskState.h index 715e4f28..5f04fef4 100644 --- a/ros/demos/smart_speaker/src/states/rss/RssAskTaskState.h +++ b/ros/demos/smart_speaker/src/states/rss/RssAskTaskState.h @@ -10,7 +10,7 @@ class RssAskTaskState : public TalkState Language language, StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle); + rclcpp::Node::SharedPtr node); ~RssAskTaskState() override = default; DECLARE_NOT_COPYABLE(RssAskTaskState); diff --git a/ros/demos/smart_speaker/src/states/rss/RssIdleState.cpp b/ros/demos/smart_speaker/src/states/rss/RssIdleState.cpp index 8bf1badc..ec8f6dfa 100644 --- a/ros/demos/smart_speaker/src/states/rss/RssIdleState.cpp +++ b/ros/demos/smart_speaker/src/states/rss/RssIdleState.cpp @@ -14,13 +14,17 @@ RssIdleState::RssIdleState( Language language, StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle) - : State(language, stateManager, desireSet, nodeHandle) + rclcpp::Node::SharedPtr node) + : State(language, stateManager, desireSet, move(node)) { - m_robotNameDetectedSubscriber = - nodeHandle.subscribe("robot_name_detected", 1, &RssIdleState::robotNameDetectedSubscriberCallback, this); - m_personNamesSubscriber = - nodeHandle.subscribe("person_names", 1, &RssIdleState::personNamesSubscriberCallback, this); + m_robotNameDetectedSubscriber = m_node->create_subscription( + "robot_name_detected", + 1, + [this](const std_msgs::msg::Empty::SharedPtr msg) { robotNameDetectedSubscriberCallback(msg); }); + m_personNamesSubscriber = m_node->create_subscription( + "person_names", + 1, + [this](const perception_msgs::msg::PersonNames::SharedPtr msg) { personNamesSubscriberCallback(msg); }); } void RssIdleState::enable(const string& parameter, const type_index& previousStageType) @@ -44,7 +48,7 @@ void RssIdleState::enable(const string& parameter, const type_index& previousSta m_desireSet->addDesire(move(faceAnimationDesire)); } -void RssIdleState::robotNameDetectedSubscriberCallback(const std_msgs::Empty::ConstPtr& msg) +void RssIdleState::robotNameDetectedSubscriberCallback(const std_msgs::msg::Empty::SharedPtr msg) { if (!enabled()) { @@ -54,7 +58,7 @@ void RssIdleState::robotNameDetectedSubscriberCallback(const std_msgs::Empty::Co m_stateManager.switchTo(); } -void RssIdleState::personNamesSubscriberCallback(const person_identification::PersonNames::ConstPtr& msg) +void RssIdleState::personNamesSubscriberCallback(const perception_msgs::msg::PersonNames::SharedPtr msg) { if (!enabled() || msg->names.size() == 0) { @@ -66,7 +70,7 @@ void RssIdleState::personNamesSubscriberCallback(const person_identification::Pe msg->names.begin(), msg->names.end(), back_inserter(names), - [](const person_identification::PersonName& name) { return name.name; }); + [](const perception_msgs::msg::PersonName& name) { return name.name; }); auto mergedNames = mergeNames(names, getAndWord()); m_stateManager.switchTo(mergedNames); diff --git a/ros/demos/smart_speaker/src/states/rss/RssIdleState.h b/ros/demos/smart_speaker/src/states/rss/RssIdleState.h index 502dd825..a3993e45 100644 --- a/ros/demos/smart_speaker/src/states/rss/RssIdleState.h +++ b/ros/demos/smart_speaker/src/states/rss/RssIdleState.h @@ -3,20 +3,20 @@ #include "../State.h" -#include -#include +#include +#include class RssIdleState : public State { - ros::Subscriber m_robotNameDetectedSubscriber; - ros::Subscriber m_personNamesSubscriber; + rclcpp::Subscription::SharedPtr m_robotNameDetectedSubscriber; + rclcpp::Subscription::SharedPtr m_personNamesSubscriber; public: RssIdleState( Language language, StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle); + rclcpp::Node::SharedPtr node); ~RssIdleState() override = default; DECLARE_NOT_COPYABLE(RssIdleState); @@ -28,8 +28,8 @@ class RssIdleState : public State void enable(const std::string& parameter, const std::type_index& previousStageType) override; private: - void robotNameDetectedSubscriberCallback(const std_msgs::Empty::ConstPtr& msg); - void personNamesSubscriberCallback(const person_identification::PersonNames::ConstPtr& msg); + void robotNameDetectedSubscriberCallback(const std_msgs::msg::Empty::SharedPtr msg); + void personNamesSubscriberCallback(const perception_msgs::msg::PersonNames::SharedPtr msg); }; inline std::type_index RssIdleState::type() const diff --git a/ros/demos/smart_speaker/src/states/rss/RssStoryState.cpp b/ros/demos/smart_speaker/src/states/rss/RssStoryState.cpp index 11b06826..e9cdd5b6 100644 --- a/ros/demos/smart_speaker/src/states/rss/RssStoryState.cpp +++ b/ros/demos/smart_speaker/src/states/rss/RssStoryState.cpp @@ -18,10 +18,10 @@ RssStoryState::RssStoryState( Language language, StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, const std::string& englishStoryPath, const std::string& frenchStoryPath) - : State(language, stateManager, desireSet, nodeHandle), + : State(language, stateManager, desireSet, move(node)), m_talkDesireId(MAX_DESIRE_ID), m_faceAnimationDesireId(MAX_DESIRE_ID) { diff --git a/ros/demos/smart_speaker/src/states/rss/RssStoryState.h b/ros/demos/smart_speaker/src/states/rss/RssStoryState.h index aec84735..3075cc4f 100644 --- a/ros/demos/smart_speaker/src/states/rss/RssStoryState.h +++ b/ros/demos/smart_speaker/src/states/rss/RssStoryState.h @@ -3,8 +3,6 @@ #include "../State.h" -#include - #include struct StoryLine @@ -26,7 +24,7 @@ class RssStoryState : public State, public DesireSetObserver Language language, StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, const std::string& englishStoryPath, const std::string& frenchStoryPath); ~RssStoryState() override; diff --git a/ros/demos/smart_speaker/src/states/rss/RssValidTaskState.cpp b/ros/demos/smart_speaker/src/states/rss/RssValidTaskState.cpp index fb51f852..abedf5f0 100644 --- a/ros/demos/smart_speaker/src/states/rss/RssValidTaskState.cpp +++ b/ros/demos/smart_speaker/src/states/rss/RssValidTaskState.cpp @@ -15,8 +15,8 @@ RssValidTaskState::RssValidTaskState( Language language, StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle) - : ValidTaskState(language, stateManager, desireSet, nodeHandle) + rclcpp::Node::SharedPtr node) + : ValidTaskState(language, stateManager, desireSet, move(node)) { } @@ -44,7 +44,7 @@ void RssValidTaskState::switchState(const string& task) } else { - ROS_ERROR_STREAM("Invalid task (" << task << ")"); + RCLCPP_ERROR_STREAM(m_node->get_logger(), "Invalid task (" << task << ")"); m_stateManager.switchTo(); } } diff --git a/ros/demos/smart_speaker/src/states/rss/RssValidTaskState.h b/ros/demos/smart_speaker/src/states/rss/RssValidTaskState.h index e703f151..ed0af36b 100644 --- a/ros/demos/smart_speaker/src/states/rss/RssValidTaskState.h +++ b/ros/demos/smart_speaker/src/states/rss/RssValidTaskState.h @@ -16,7 +16,7 @@ class RssValidTaskState : public ValidTaskState Language language, StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle); + rclcpp::Node::SharedPtr node); ~RssValidTaskState() override = default; DECLARE_NOT_COPYABLE(RssValidTaskState); diff --git a/ros/demos/smart_speaker/src/states/rss/RssWaitAnswerState.cpp b/ros/demos/smart_speaker/src/states/rss/RssWaitAnswerState.cpp index 0221cf9b..76fa6b9c 100644 --- a/ros/demos/smart_speaker/src/states/rss/RssWaitAnswerState.cpp +++ b/ros/demos/smart_speaker/src/states/rss/RssWaitAnswerState.cpp @@ -30,8 +30,8 @@ RssWaitAnswerState::RssWaitAnswerState( Language language, StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle) - : WaitAnswerState(language, stateManager, desireSet, nodeHandle) + rclcpp::Node::SharedPtr node) + : WaitAnswerState(language, stateManager, desireSet, move(node)) { switch (language) { diff --git a/ros/demos/smart_speaker/src/states/rss/RssWaitAnswerState.h b/ros/demos/smart_speaker/src/states/rss/RssWaitAnswerState.h index ee8c177c..996cd1a5 100644 --- a/ros/demos/smart_speaker/src/states/rss/RssWaitAnswerState.h +++ b/ros/demos/smart_speaker/src/states/rss/RssWaitAnswerState.h @@ -3,8 +3,6 @@ #include "../common/WaitAnswerState.h" -#include - class RssWaitAnswerState : public WaitAnswerState { std::string m_weatherWord; @@ -18,7 +16,7 @@ class RssWaitAnswerState : public WaitAnswerState Language language, StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle); + rclcpp::Node::SharedPtr node); ~RssWaitAnswerState() override = default; DECLARE_NOT_COPYABLE(RssWaitAnswerState); diff --git a/ros/demos/smart_speaker/src/states/rss/RssWaitPersonIdentificationState.cpp b/ros/demos/smart_speaker/src/states/rss/RssWaitPersonIdentificationState.cpp index f7887d33..492a77c6 100644 --- a/ros/demos/smart_speaker/src/states/rss/RssWaitPersonIdentificationState.cpp +++ b/ros/demos/smart_speaker/src/states/rss/RssWaitPersonIdentificationState.cpp @@ -14,11 +14,13 @@ RssWaitPersonIdentificationState::RssWaitPersonIdentificationState( Language language, StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle) - : State(language, stateManager, desireSet, nodeHandle) + rclcpp::Node::SharedPtr node) + : State(language, stateManager, desireSet, move(node)) { - m_personNamesSubscriber = - nodeHandle.subscribe("person_names", 1, &RssWaitPersonIdentificationState::personNamesSubscriberCallback, this); + m_personNamesSubscriber = m_node->create_subscription( + "person_names", + 1, + [this](const perception_msgs::msg::PersonNames::SharedPtr msg) { personNamesSubscriberCallback(msg); }); } void RssWaitPersonIdentificationState::enable(const string& parameter, const type_index& previousStageType) @@ -41,26 +43,22 @@ void RssWaitPersonIdentificationState::enable(const string& parameter, const typ m_desireSet->addDesire(move(soundFollowingDesire)); m_desireSet->addDesire(move(faceAnimationDesire)); - constexpr bool oneshot = true; - m_timeoutTimer = m_nodeHandle.createTimer( - ros::Duration(TIMEOUT_S), - &RssWaitPersonIdentificationState::timeoutTimerCallback, - this, - oneshot); + m_timeoutTimer = m_node->create_wall_timer(chrono::seconds(TIMEOUT_S), [this]() { timeoutTimerCallback(); }); } void RssWaitPersonIdentificationState::disable() { State::disable(); - if (m_timeoutTimer.isValid()) + if (m_timeoutTimer) { - m_timeoutTimer.stop(); + m_timeoutTimer->cancel(); + m_timeoutTimer = nullptr; } } void RssWaitPersonIdentificationState::personNamesSubscriberCallback( - const person_identification::PersonNames::ConstPtr& msg) + const perception_msgs::msg::PersonNames::SharedPtr msg) { if (!enabled() || msg->names.size() == 0) { @@ -72,13 +70,13 @@ void RssWaitPersonIdentificationState::personNamesSubscriberCallback( msg->names.begin(), msg->names.end(), back_inserter(names), - [](const person_identification::PersonName& name) { return name.name; }); + [](const perception_msgs::msg::PersonName& name) { return name.name; }); auto mergedNames = mergeNames(names, getAndWord()); m_stateManager.switchTo(mergedNames); } -void RssWaitPersonIdentificationState::timeoutTimerCallback(const ros::TimerEvent& event) +void RssWaitPersonIdentificationState::timeoutTimerCallback() { if (!enabled()) { diff --git a/ros/demos/smart_speaker/src/states/rss/RssWaitPersonIdentificationState.h b/ros/demos/smart_speaker/src/states/rss/RssWaitPersonIdentificationState.h index 2d484ff8..1182d1cd 100644 --- a/ros/demos/smart_speaker/src/states/rss/RssWaitPersonIdentificationState.h +++ b/ros/demos/smart_speaker/src/states/rss/RssWaitPersonIdentificationState.h @@ -3,19 +3,19 @@ #include "../State.h" -#include +#include class RssWaitPersonIdentificationState : public State { - ros::Subscriber m_personNamesSubscriber; - ros::Timer m_timeoutTimer; + rclcpp::Subscription::SharedPtr m_personNamesSubscriber; + rclcpp::TimerBase::SharedPtr m_timeoutTimer; public: RssWaitPersonIdentificationState( Language language, StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle); + rclcpp::Node::SharedPtr node); ~RssWaitPersonIdentificationState() override = default; DECLARE_NOT_COPYABLE(RssWaitPersonIdentificationState); @@ -28,8 +28,8 @@ class RssWaitPersonIdentificationState : public State void disable() override; private: - void personNamesSubscriberCallback(const person_identification::PersonNames::ConstPtr& msg); - void timeoutTimerCallback(const ros::TimerEvent& event); + void personNamesSubscriberCallback(const perception_msgs::msg::PersonNames::SharedPtr msg); + void timeoutTimerCallback(); }; inline std::type_index RssWaitPersonIdentificationState::type() const diff --git a/ros/demos/smart_speaker/src/states/smart/SmartAskOtherTaskState.cpp b/ros/demos/smart_speaker/src/states/smart/SmartAskOtherTaskState.cpp index 4c4bb152..c63167f3 100644 --- a/ros/demos/smart_speaker/src/states/smart/SmartAskOtherTaskState.cpp +++ b/ros/demos/smart_speaker/src/states/smart/SmartAskOtherTaskState.cpp @@ -14,9 +14,9 @@ SmartAskOtherTaskState::SmartAskOtherTaskState( Language language, StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, bool singleTaskPerPerson) - : TalkState(language, stateManager, desireSet, nodeHandle, type_index(typeid(SmartWaitAnswerState))), + : TalkState(language, stateManager, desireSet, move(node), type_index(typeid(SmartWaitAnswerState))), m_singleTaskPerPerson(singleTaskPerPerson) { } diff --git a/ros/demos/smart_speaker/src/states/smart/SmartAskOtherTaskState.h b/ros/demos/smart_speaker/src/states/smart/SmartAskOtherTaskState.h index 410875ab..e3e5a321 100644 --- a/ros/demos/smart_speaker/src/states/smart/SmartAskOtherTaskState.h +++ b/ros/demos/smart_speaker/src/states/smart/SmartAskOtherTaskState.h @@ -15,7 +15,7 @@ class SmartAskOtherTaskState : public TalkState Language language, StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, bool singleTaskPerPerson); ~SmartAskOtherTaskState() override = default; diff --git a/ros/demos/smart_speaker/src/states/smart/SmartAskTaskState.cpp b/ros/demos/smart_speaker/src/states/smart/SmartAskTaskState.cpp index 8ea9833b..f19caf23 100644 --- a/ros/demos/smart_speaker/src/states/smart/SmartAskTaskState.cpp +++ b/ros/demos/smart_speaker/src/states/smart/SmartAskTaskState.cpp @@ -13,9 +13,9 @@ SmartAskTaskState::SmartAskTaskState( Language language, StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, vector songNames) - : TalkState(language, stateManager, desireSet, nodeHandle, type_index(typeid(SmartWaitAnswerState))), + : TalkState(language, stateManager, desireSet, move(node), type_index(typeid(SmartWaitAnswerState))), m_songNames(move(songNames)) { } diff --git a/ros/demos/smart_speaker/src/states/smart/SmartAskTaskState.h b/ros/demos/smart_speaker/src/states/smart/SmartAskTaskState.h index 220b9218..ede28ef9 100644 --- a/ros/demos/smart_speaker/src/states/smart/SmartAskTaskState.h +++ b/ros/demos/smart_speaker/src/states/smart/SmartAskTaskState.h @@ -15,7 +15,7 @@ class SmartAskTaskState : public TalkState Language language, StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, std::vector songNames); ~SmartAskTaskState() override = default; diff --git a/ros/demos/smart_speaker/src/states/smart/SmartIdleState.cpp b/ros/demos/smart_speaker/src/states/smart/SmartIdleState.cpp index 25312c21..e14ff749 100644 --- a/ros/demos/smart_speaker/src/states/smart/SmartIdleState.cpp +++ b/ros/demos/smart_speaker/src/states/smart/SmartIdleState.cpp @@ -7,6 +7,10 @@ #include +#include +#include +#include + #include #include #include @@ -17,13 +21,13 @@ SmartIdleState::SmartIdleState( Language language, StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, double personDistanceThreshold, std::string personDistanceFrameId, double noseConfidenceThreshold, size_t videoAnalysisMessageCountThreshold, size_t videoAnalysisMessageCountTolerance) - : State(language, stateManager, desireSet, nodeHandle), + : State(language, stateManager, desireSet, move(node)), m_personDistanceThreshold(personDistanceThreshold), m_personDistanceFrameId(personDistanceFrameId), m_noseConfidenceThreshold(noseConfidenceThreshold), @@ -32,11 +36,18 @@ SmartIdleState::SmartIdleState( m_videoAnalysisValidMessageCount(0), m_videoAnalysisInvalidMessageCount(0) { - m_personNamesSubscriber = - nodeHandle.subscribe("person_names", 1, &SmartIdleState::personNamesSubscriberCallback, this); - - m_videoAnalysisSubscriber = - nodeHandle.subscribe("video_analysis", 1, &SmartIdleState::videoAnalysisSubscriberCallback, this); + m_personNamesSubscriber = m_node->create_subscription( + "person_names", + 1, + [this](const perception_msgs::msg::PersonNames::SharedPtr msg) { personNamesSubscriberCallback(msg); }); + + m_videoAnalysisSubscriber = m_node->create_subscription( + "video_analysis", + 1, + [this](const perception_msgs::msg::VideoAnalysis::SharedPtr msg) { videoAnalysisSubscriberCallback(msg); }); + + m_tfBuffer = make_unique(m_node->get_clock()); + m_tfListener = make_shared(*m_tfBuffer); } void SmartIdleState::enable(const string& parameter, const type_index& previousStageType) @@ -57,7 +68,7 @@ void SmartIdleState::enable(const string& parameter, const type_index& previousS m_desireSet->addDesire(move(faceAnimationDesire)); } -void SmartIdleState::personNamesSubscriberCallback(const person_identification::PersonNames::ConstPtr& msg) +void SmartIdleState::personNamesSubscriberCallback(const perception_msgs::msg::PersonNames::SharedPtr msg) { if (!enabled() || msg->names.size() == 0) { @@ -75,7 +86,7 @@ void SmartIdleState::personNamesSubscriberCallback(const person_identification:: } } -void SmartIdleState::videoAnalysisSubscriberCallback(const video_analyzer::VideoAnalysis::ConstPtr& msg) +void SmartIdleState::videoAnalysisSubscriberCallback(const perception_msgs::msg::VideoAnalysis::SharedPtr msg) { if (!enabled() || msg->objects.size() == 0) { @@ -83,20 +94,22 @@ void SmartIdleState::videoAnalysisSubscriberCallback(const video_analyzer::Video } if (!msg->contains_3d_positions) { - ROS_ERROR("The video analysis must contain 3d positions."); + RCLCPP_ERROR(m_node->get_logger(), "The video analysis must contain 3d positions."); return; } - tf::StampedTransform transform; + geometry_msgs::msg::TransformStamped transformMsg; try { - m_tfListener.lookupTransform(m_personDistanceFrameId, msg->header.frame_id, msg->header.stamp, transform); + transformMsg = m_tfBuffer->lookupTransform(m_personDistanceFrameId, msg->header.frame_id, msg->header.stamp); } - catch (tf::TransformException& ex) + catch (tf2::TransformException& ex) { - ROS_ERROR("%s", ex.what()); + RCLCPP_ERROR(m_node->get_logger(), "%s", ex.what()); return; } + tf2::Stamped transform; + tf2::convert(transformMsg, transform); bool faceFound = false; for (auto& object : msg->objects) @@ -125,7 +138,7 @@ void SmartIdleState::videoAnalysisSubscriberCallback(const video_analyzer::Video } } -double SmartIdleState::personNameDistance(const person_identification::PersonName& name) +double SmartIdleState::personNameDistance(const perception_msgs::msg::PersonName& name) { if (name.position_3d.size() == 0) { @@ -134,23 +147,25 @@ double SmartIdleState::personNameDistance(const person_identification::PersonNam try { - tf::StampedTransform transform; - m_tfListener.lookupTransform(m_personDistanceFrameId, name.frame_id, ros::Time(0), transform); + geometry_msgs::msg::TransformStamped transformMsg = + m_tfBuffer->lookupTransform(m_personDistanceFrameId, name.frame_id, tf2::TimePointZero); + tf2::Stamped transform; + tf2::convert(transformMsg, transform); - tf::Vector3 p(name.position_3d[0].x, name.position_3d[0].y, name.position_3d[0].z); + tf2::Vector3 p(name.position_3d[0].x, name.position_3d[0].y, name.position_3d[0].z); p = transform * p; return p.length(); } - catch (tf::TransformException& ex) + catch (tf2::TransformException& ex) { - ROS_ERROR("%s", ex.what()); + RCLCPP_ERROR(m_node->get_logger(), "%s", ex.what()); return numeric_limits::infinity(); } } double SmartIdleState::faceDistance( - const video_analyzer::VideoAnalysisObject& object, - const tf::StampedTransform& transform) + const perception_msgs::msg::VideoAnalysisObject& object, + const tf2::Stamped& transform) { constexpr size_t PERSON_POSE_NOSE_INDEX = 0; @@ -162,7 +177,7 @@ double SmartIdleState::faceDistance( } auto nosePoint = object.person_pose_3d[PERSON_POSE_NOSE_INDEX]; - tf::Vector3 p(nosePoint.x, nosePoint.y, nosePoint.z); + tf2::Vector3 p(nosePoint.x, nosePoint.y, nosePoint.z); p = transform * p; return p.length(); } diff --git a/ros/demos/smart_speaker/src/states/smart/SmartIdleState.h b/ros/demos/smart_speaker/src/states/smart/SmartIdleState.h index ab89ee38..84024f2b 100644 --- a/ros/demos/smart_speaker/src/states/smart/SmartIdleState.h +++ b/ros/demos/smart_speaker/src/states/smart/SmartIdleState.h @@ -3,11 +3,12 @@ #include "../State.h" -#include +#include +#include +#include -#include -#include -#include +#include +#include class SmartIdleState : public State { @@ -20,17 +21,18 @@ class SmartIdleState : public State size_t m_videoAnalysisValidMessageCount; size_t m_videoAnalysisInvalidMessageCount; - tf::TransformListener m_tfListener; + std::unique_ptr m_tfBuffer; + std::shared_ptr m_tfListener; - ros::Subscriber m_personNamesSubscriber; - ros::Subscriber m_videoAnalysisSubscriber; + rclcpp::Subscription::SharedPtr m_personNamesSubscriber; + rclcpp::Subscription::SharedPtr m_videoAnalysisSubscriber; public: SmartIdleState( Language language, StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, double personDistanceThreshold, std::string personDistanceFrameId, double noseConfidenceThreshold, @@ -47,11 +49,13 @@ class SmartIdleState : public State void enable(const std::string& parameter, const std::type_index& previousStageType) override; private: - void personNamesSubscriberCallback(const person_identification::PersonNames::ConstPtr& msg); - void videoAnalysisSubscriberCallback(const video_analyzer::VideoAnalysis::ConstPtr& msg); + void personNamesSubscriberCallback(const perception_msgs::msg::PersonNames::SharedPtr msg); + void videoAnalysisSubscriberCallback(const perception_msgs::msg::VideoAnalysis::SharedPtr msg); - double personNameDistance(const person_identification::PersonName& name); - double faceDistance(const video_analyzer::VideoAnalysisObject& object, const tf::StampedTransform& transform); + double personNameDistance(const perception_msgs::msg::PersonName& name); + double faceDistance( + const perception_msgs::msg::VideoAnalysisObject& object, + const tf2::Stamped& transform); }; inline std::type_index SmartIdleState::type() const diff --git a/ros/demos/smart_speaker/src/states/smart/SmartThankYouState.cpp b/ros/demos/smart_speaker/src/states/smart/SmartThankYouState.cpp index 757269ba..2de3c255 100644 --- a/ros/demos/smart_speaker/src/states/smart/SmartThankYouState.cpp +++ b/ros/demos/smart_speaker/src/states/smart/SmartThankYouState.cpp @@ -12,8 +12,8 @@ SmartThankYouState::SmartThankYouState( Language language, StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle) - : TalkState(language, stateManager, desireSet, nodeHandle, type_index(typeid(AfterTaskDelayState))) + rclcpp::Node::SharedPtr node) + : TalkState(language, stateManager, desireSet, move(node), type_index(typeid(AfterTaskDelayState))) { } diff --git a/ros/demos/smart_speaker/src/states/smart/SmartThankYouState.h b/ros/demos/smart_speaker/src/states/smart/SmartThankYouState.h index e1fc6ffa..f10e78fa 100644 --- a/ros/demos/smart_speaker/src/states/smart/SmartThankYouState.h +++ b/ros/demos/smart_speaker/src/states/smart/SmartThankYouState.h @@ -2,9 +2,6 @@ #define SMART_SPEAKER_STATES_SMART_SMART_THANK_YOU_STATE_H #include "../common/TalkState.h" - -#include - #include #include @@ -15,7 +12,7 @@ class SmartThankYouState : public TalkState Language language, StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle); + rclcpp::Node::SharedPtr node); ~SmartThankYouState() override = default; DECLARE_NOT_COPYABLE(SmartThankYouState); diff --git a/ros/demos/smart_speaker/src/states/smart/SmartValidTaskState.cpp b/ros/demos/smart_speaker/src/states/smart/SmartValidTaskState.cpp index 02bd42b6..c6b7788b 100644 --- a/ros/demos/smart_speaker/src/states/smart/SmartValidTaskState.cpp +++ b/ros/demos/smart_speaker/src/states/smart/SmartValidTaskState.cpp @@ -14,8 +14,8 @@ SmartValidTaskState::SmartValidTaskState( Language language, StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle) - : ValidTaskState(language, stateManager, desireSet, nodeHandle) + rclcpp::Node::SharedPtr node) + : ValidTaskState(language, stateManager, desireSet, move(node)) { } @@ -32,7 +32,7 @@ void SmartValidTaskState::switchState(const string& task) } else { - ROS_ERROR_STREAM("Invalid task (" << task << ")"); + RCLCPP_ERROR_STREAM(m_node->get_logger(), "Invalid task (" << task << ")"); m_stateManager.switchTo(); } } diff --git a/ros/demos/smart_speaker/src/states/smart/SmartValidTaskState.h b/ros/demos/smart_speaker/src/states/smart/SmartValidTaskState.h index 317da1fa..b155bbdf 100644 --- a/ros/demos/smart_speaker/src/states/smart/SmartValidTaskState.h +++ b/ros/demos/smart_speaker/src/states/smart/SmartValidTaskState.h @@ -13,7 +13,7 @@ class SmartValidTaskState : public ValidTaskState Language language, StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle); + rclcpp::Node::SharedPtr node); ~SmartValidTaskState() override = default; DECLARE_NOT_COPYABLE(SmartValidTaskState); diff --git a/ros/demos/smart_speaker/src/states/smart/SmartWaitAnswerState.cpp b/ros/demos/smart_speaker/src/states/smart/SmartWaitAnswerState.cpp index cbc8fb19..08f5ffd3 100644 --- a/ros/demos/smart_speaker/src/states/smart/SmartWaitAnswerState.cpp +++ b/ros/demos/smart_speaker/src/states/smart/SmartWaitAnswerState.cpp @@ -29,9 +29,9 @@ SmartWaitAnswerState::SmartWaitAnswerState( Language language, StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, vector> songKeywords) - : WaitAnswerState(language, stateManager, desireSet, nodeHandle), + : WaitAnswerState(language, stateManager, desireSet, move(node)), m_songKeywords(move(songKeywords)) { if (m_songKeywords.size() == 0) @@ -82,7 +82,7 @@ void SmartWaitAnswerState::switchStateAfterTranscriptReceived(const std::string& } else if (isFinal) { - ROS_WARN_STREAM("Invalid task (" << text << ")"); + RCLCPP_WARN_STREAM(m_node->get_logger(), "Invalid task (" << text << ")"); m_stateManager.switchTo(); } } diff --git a/ros/demos/smart_speaker/src/states/smart/SmartWaitAnswerState.h b/ros/demos/smart_speaker/src/states/smart/SmartWaitAnswerState.h index 9d519828..d3bb2e11 100644 --- a/ros/demos/smart_speaker/src/states/smart/SmartWaitAnswerState.h +++ b/ros/demos/smart_speaker/src/states/smart/SmartWaitAnswerState.h @@ -3,8 +3,6 @@ #include "../common/WaitAnswerState.h" -#include - #include class SmartWaitAnswerState : public WaitAnswerState @@ -20,7 +18,7 @@ class SmartWaitAnswerState : public WaitAnswerState Language language, StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, std::vector> songKeywords); ~SmartWaitAnswerState() override = default; diff --git a/ros/demos/smart_speaker/src/states/task/CurrentWeatherState.cpp b/ros/demos/smart_speaker/src/states/task/CurrentWeatherState.cpp index 9d12eb22..24d582e4 100644 --- a/ros/demos/smart_speaker/src/states/task/CurrentWeatherState.cpp +++ b/ros/demos/smart_speaker/src/states/task/CurrentWeatherState.cpp @@ -8,31 +8,38 @@ using namespace std; +constexpr chrono::seconds WEATHER_SERVICE_TIMEOUT(20); + CurrentWeatherState::CurrentWeatherState( Language language, StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, type_index nextStateType) - : TalkState(language, stateManager, desireSet, nodeHandle, nextStateType) + : TalkState(language, stateManager, desireSet, move(node), nextStateType) { + m_weatherClientCallbackGroup = m_node->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive); + m_weatherClient = m_node->create_client( + "cloud_data/current_local_weather", + rmw_qos_profile_services_default, + m_weatherClientCallbackGroup); } string CurrentWeatherState::generateEnglishText(const string& _) { bool ok; - cloud_data::CurrentLocalWeather srv; - getCurrentLocalWeather(ok, srv); + cloud_data::srv::CurrentLocalWeather::Response response; + getCurrentLocalWeather(ok, response); stringstream ss; ss.precision(FLOAT_NUMBER_PRECISION); if (ok) { - ss << "The current temperature is " << srv.response.temperature_celsius << " degree Celsius and "; - ss << " it feels like " << srv.response.feels_like_temperature_celsius << " degree Celsius. "; - ss << "Humidity is " << srv.response.humidity_percent << "% and "; - ss << " wind speed is " << srv.response.wind_speed_kph << " kilometers per hour. "; + ss << "The current temperature is " << response.temperature_celsius << " degree Celsius and "; + ss << " it feels like " << response.feels_like_temperature_celsius << " degree Celsius. "; + ss << "Humidity is " << response.humidity_percent << "% and "; + ss << " wind speed is " << response.wind_speed_kph << " kilometers per hour. "; } else { @@ -45,18 +52,19 @@ string CurrentWeatherState::generateEnglishText(const string& _) string CurrentWeatherState::generateFrenchText(const string& _) { bool ok; - cloud_data::CurrentLocalWeather srv; - getCurrentLocalWeather(ok, srv); + cloud_data::srv::CurrentLocalWeather::Response response; + getCurrentLocalWeather(ok, response); stringstream ss; ss.precision(FLOAT_NUMBER_PRECISION); if (ok) { - ss << "La température courante est de " << srv.response.temperature_celsius << " degré Celsius. "; - ss << "La température courante ressentie est de " << srv.response.feels_like_temperature_celsius << " degré Celsius. "; - ss << "L'humidité courante est de " << srv.response.humidity_percent << "%. "; - ss << "La vitesse courante du vent est de " << srv.response.wind_speed_kph << " kilomètres par heure. "; + ss << "La température courante est de " << response.temperature_celsius << " degré Celsius. "; + ss << "La température courante ressentie est de " << response.feels_like_temperature_celsius + << " degré Celsius. "; + ss << "L'humidité courante est de " << response.humidity_percent << "%. "; + ss << "La vitesse courante du vent est de " << response.wind_speed_kph << " kilomètres par heure. "; } else { @@ -66,10 +74,18 @@ string CurrentWeatherState::generateFrenchText(const string& _) return ss.str(); } -void CurrentWeatherState::getCurrentLocalWeather(bool& ok, cloud_data::CurrentLocalWeather& srv) +void CurrentWeatherState::getCurrentLocalWeather(bool& ok, cloud_data::srv::CurrentLocalWeather::Response& response) { - ros::ServiceClient service = - m_nodeHandle.serviceClient("cloud_data/current_local_weather"); - - ok = service.exists() && service.call(srv); + auto request = make_shared(); + auto future = m_weatherClient->async_send_request(request); + auto status = future.wait_for(WEATHER_SERVICE_TIMEOUT); + if (status == future_status::ready) + { + response = *future.get(); + ok = response.ok; + } + else + { + ok = false; + } } diff --git a/ros/demos/smart_speaker/src/states/task/CurrentWeatherState.h b/ros/demos/smart_speaker/src/states/task/CurrentWeatherState.h index fca757a2..1bbe728a 100644 --- a/ros/demos/smart_speaker/src/states/task/CurrentWeatherState.h +++ b/ros/demos/smart_speaker/src/states/task/CurrentWeatherState.h @@ -3,16 +3,19 @@ #include "../common/TalkState.h" -#include +#include class CurrentWeatherState : public TalkState { + rclcpp::CallbackGroup::SharedPtr m_weatherClientCallbackGroup; + rclcpp::Client::SharedPtr m_weatherClient; + public: CurrentWeatherState( Language language, StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, std::type_index nextStateType); ~CurrentWeatherState() override = default; @@ -26,7 +29,7 @@ class CurrentWeatherState : public TalkState std::string generateFrenchText(const std::string& _) override; private: - void getCurrentLocalWeather(bool& ok, cloud_data::CurrentLocalWeather& srv); + void getCurrentLocalWeather(bool& ok, cloud_data::srv::CurrentLocalWeather::Response& response); }; inline std::type_index CurrentWeatherState::type() const diff --git a/ros/demos/smart_speaker/src/states/task/DancePlayedSongState.cpp b/ros/demos/smart_speaker/src/states/task/DancePlayedSongState.cpp index 17427a3e..4cc81f2d 100644 --- a/ros/demos/smart_speaker/src/states/task/DancePlayedSongState.cpp +++ b/ros/demos/smart_speaker/src/states/task/DancePlayedSongState.cpp @@ -10,10 +10,10 @@ DancePlayedSongState::DancePlayedSongState( Language language, StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, type_index nextStateType, vector songPaths) - : State(language, stateManager, desireSet, nodeHandle), + : State(language, stateManager, desireSet, move(node)), m_nextStateType(nextStateType), m_songPaths(move(songPaths)), m_songDesireId(MAX_DESIRE_ID) @@ -25,8 +25,10 @@ DancePlayedSongState::DancePlayedSongState( m_desireSet->addObserver(this); - m_songStartedSubscriber = - nodeHandle.subscribe("sound_player/started", 1, &DancePlayedSongState::songStartedSubscriberCallback, this); + m_songStartedSubscriber = m_node->create_subscription( + "sound_player/started", + 1, + [this](const behavior_msgs::msg::SoundStarted::SharedPtr msg) { songStartedSubscriberCallback(msg); }); } DancePlayedSongState::~DancePlayedSongState() @@ -51,7 +53,7 @@ void DancePlayedSongState::enable(const string& parameter, const type_index& pre size_t songIndex = atoi(parameter.c_str()); if (songIndex >= m_songPaths.size()) { - ROS_ERROR("The song index is invalid."); + RCLCPP_ERROR(m_node->get_logger(), "The song index is invalid."); m_stateManager.switchTo(m_nextStateType); } else @@ -75,7 +77,7 @@ void DancePlayedSongState::disable() m_songDesireId = MAX_DESIRE_ID; } -void DancePlayedSongState::songStartedSubscriberCallback(const sound_player::Started::ConstPtr& msg) +void DancePlayedSongState::songStartedSubscriberCallback(const behavior_msgs::msg::SoundStarted::SharedPtr msg) { if (!enabled() || msg->id != m_songDesireId) { diff --git a/ros/demos/smart_speaker/src/states/task/DancePlayedSongState.h b/ros/demos/smart_speaker/src/states/task/DancePlayedSongState.h index 9ad1c327..365e227c 100644 --- a/ros/demos/smart_speaker/src/states/task/DancePlayedSongState.h +++ b/ros/demos/smart_speaker/src/states/task/DancePlayedSongState.h @@ -3,13 +3,13 @@ #include "../State.h" -#include +#include class DancePlayedSongState : public State, public DesireSetObserver { std::type_index m_nextStateType; - ros::Subscriber m_songStartedSubscriber; + rclcpp::Subscription::SharedPtr m_songStartedSubscriber; std::vector m_songPaths; uint64_t m_songDesireId; @@ -19,7 +19,7 @@ class DancePlayedSongState : public State, public DesireSetObserver Language language, StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, std::type_index nextStateType, std::vector songPaths); ~DancePlayedSongState() override; @@ -36,7 +36,7 @@ class DancePlayedSongState : public State, public DesireSetObserver void disable() override; private: - void songStartedSubscriberCallback(const sound_player::Started::ConstPtr& msg); + void songStartedSubscriberCallback(const behavior_msgs::msg::SoundStarted::SharedPtr msg); }; inline std::type_index DancePlayedSongState::type() const diff --git a/ros/demos/smart_speaker/src/states/task/DanceState.cpp b/ros/demos/smart_speaker/src/states/task/DanceState.cpp index 2ff23e04..c51760e1 100644 --- a/ros/demos/smart_speaker/src/states/task/DanceState.cpp +++ b/ros/demos/smart_speaker/src/states/task/DanceState.cpp @@ -10,9 +10,9 @@ DanceState::DanceState( Language language, StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, type_index nextStateType) - : State(language, stateManager, desireSet, nodeHandle), + : State(language, stateManager, desireSet, move(node)), m_nextStateType(nextStateType) { } @@ -31,22 +31,21 @@ void DanceState::enable(const string& parameter, const type_index& previousStage m_desireSet->addDesire(move(danceDesire)); m_desireSet->addDesire(move(faceAnimationDesire)); - constexpr bool oneshot = true; - m_timeoutTimer = - m_nodeHandle.createTimer(ros::Duration(DANCE_TIMEOUT_S), &DanceState::timeoutTimerCallback, this, oneshot); + m_timeoutTimer = m_node->create_wall_timer(chrono::seconds(DANCE_TIMEOUT_S), [this]() { timeoutTimerCallback(); }); } void DanceState::disable() { State::disable(); - if (m_timeoutTimer.isValid()) + if (m_timeoutTimer) { - m_timeoutTimer.stop(); + m_timeoutTimer->cancel(); + m_timeoutTimer = nullptr; } } -void DanceState::timeoutTimerCallback(const ros::TimerEvent& event) +void DanceState::timeoutTimerCallback() { if (!enabled()) { diff --git a/ros/demos/smart_speaker/src/states/task/DanceState.h b/ros/demos/smart_speaker/src/states/task/DanceState.h index d02f5af3..37bffaec 100644 --- a/ros/demos/smart_speaker/src/states/task/DanceState.h +++ b/ros/demos/smart_speaker/src/states/task/DanceState.h @@ -3,20 +3,20 @@ #include "../State.h" -constexpr double DANCE_TIMEOUT_S = 60; +constexpr int DANCE_TIMEOUT_S = 60; class DanceState : public State { std::type_index m_nextStateType; - ros::Timer m_timeoutTimer; + rclcpp::TimerBase::SharedPtr m_timeoutTimer; public: DanceState( Language language, StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, std::type_index nextStateType); ~DanceState() override = default; @@ -30,7 +30,7 @@ class DanceState : public State void disable() override; private: - void timeoutTimerCallback(const ros::TimerEvent& event); + void timeoutTimerCallback(); }; inline std::type_index DanceState::type() const diff --git a/ros/demos/smart_speaker/src/states/task/WeatherForecastState.cpp b/ros/demos/smart_speaker/src/states/task/WeatherForecastState.cpp index 052ab1c6..37c95248 100644 --- a/ros/demos/smart_speaker/src/states/task/WeatherForecastState.cpp +++ b/ros/demos/smart_speaker/src/states/task/WeatherForecastState.cpp @@ -8,49 +8,56 @@ using namespace std; +constexpr chrono::seconds WEATHER_SERVICE_TIMEOUT(20); + WeatherForecastState::WeatherForecastState( Language language, StateManager& stateManager, shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, std::type_index nextStateType) - : TalkState(language, stateManager, desireSet, nodeHandle, nextStateType) + : TalkState(language, stateManager, desireSet, move(node), nextStateType) { + m_weatherClientCallbackGroup = m_node->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive); + m_weatherClient = m_node->create_client( + "cloud_data/local_weather_forecast", + rmw_qos_profile_services_default, + m_weatherClientCallbackGroup); } string WeatherForecastState::generateEnglishText(const string& _) { bool ok; - cloud_data::LocalWeatherForecast srv; - getLocalWeatherForecast(ok, srv); + cloud_data::srv::LocalWeatherForecast::Response response; + getLocalWeatherForecast(ok, response); stringstream ss; ss.precision(FLOAT_NUMBER_PRECISION); if (ok) { - ss << "Tomorrow morning, the temperature will be " << srv.response.temperature_morning_celsius + ss << "Tomorrow morning, the temperature will be " << response.temperature_morning_celsius << " degree Celsius and "; - ss << "the feels like temperature will be " << srv.response.feals_like_temperature_morning_celsius + ss << "the feels like temperature will be " << response.feals_like_temperature_morning_celsius << " degree Celsius. "; - ss << "During the day of tomorrow, the temperature will be " << srv.response.temperature_day_celsius + ss << "During the day of tomorrow, the temperature will be " << response.temperature_day_celsius << " degree Celsius and "; - ss << "the feels like temperature will be " << srv.response.feals_like_temperature_day_celsius + ss << "the feels like temperature will be " << response.feals_like_temperature_day_celsius << " degree Celsius. "; - ss << "Tomorrow evening, the temperature will be " << srv.response.temperature_evening_celsius + ss << "Tomorrow evening, the temperature will be " << response.temperature_evening_celsius << " degree Celsius and "; - ss << "the feels like temperature will be " << srv.response.feals_like_temperature_evening_celsius + ss << "the feels like temperature will be " << response.feals_like_temperature_evening_celsius << " degree Celsius. "; - ss << "Tomorrow night, the temperature will be " << srv.response.temperature_night_celsius + ss << "Tomorrow night, the temperature will be " << response.temperature_night_celsius << " degree Celsius and "; - ss << "the feels like temperature will be " << srv.response.feals_like_temperature_night_celsius + ss << "the feels like temperature will be " << response.feals_like_temperature_night_celsius << " degree Celsius. "; - ss << "Tomorrow, the humidity will be " << srv.response.humidity_percent << "%, "; - ss << "the wind speed will be " << srv.response.wind_speed_kph << " kilometers per hour,"; + ss << "Tomorrow, the humidity will be " << response.humidity_percent << "%, "; + ss << "the wind speed will be " << response.wind_speed_kph << " kilometers per hour,"; } else { @@ -63,28 +70,33 @@ string WeatherForecastState::generateEnglishText(const string& _) string WeatherForecastState::generateFrenchText(const string& _) { bool ok; - cloud_data::LocalWeatherForecast srv; - getLocalWeatherForecast(ok, srv); + cloud_data::srv::LocalWeatherForecast::Response response; + getLocalWeatherForecast(ok, response); stringstream ss; ss.precision(FLOAT_NUMBER_PRECISION); if (ok) { - ss << "Demain matin, la température sera de " << srv.response.temperature_morning_celsius << " degré Celsius et "; - ss << "la température ressentie sera de " << srv.response.feals_like_temperature_morning_celsius << " degré Celsius. "; + ss << "Demain matin, la température sera de " << response.temperature_morning_celsius << " degré Celsius et "; + ss << "la température ressentie sera de " << response.feals_like_temperature_morning_celsius + << " degré Celsius. "; - ss << "Demain en journée, la température sera de " << srv.response.temperature_day_celsius << " degré Celsius et "; - ss << "la température ressentie sera de " << srv.response.feals_like_temperature_day_celsius << " degré Celsius. "; + ss << "Demain en journée, la température sera de " << response.temperature_day_celsius << " degré Celsius et "; + ss << "la température ressentie sera de " << response.feals_like_temperature_day_celsius << " degré Celsius. "; - ss << "Demain en soirée, la température sera de " << srv.response.temperature_evening_celsius << " degré Celsius et "; - ss << "la température ressentie sera de " << srv.response.feals_like_temperature_evening_celsius << " degré Celsius. "; + ss << "Demain en soirée, la température sera de " << response.temperature_evening_celsius + << " degré Celsius et "; + ss << "la température ressentie sera de " << response.feals_like_temperature_evening_celsius + << " degré Celsius. "; - ss << "La nuit prochaine, la température sera de " << srv.response.temperature_night_celsius << " degré Celsius et "; - ss << "la température ressentie sera de " << srv.response.feals_like_temperature_night_celsius << " degré Celsius. "; + ss << "La nuit prochaine, la température sera de " << response.temperature_night_celsius + << " degré Celsius et "; + ss << "la température ressentie sera de " << response.feals_like_temperature_night_celsius + << " degré Celsius. "; - ss << "Demain, l'humidité sera de " << srv.response.humidity_percent << "%, "; - ss << "la vitesse du vent sera de " << srv.response.wind_speed_kph << " kilomètres par heure, "; + ss << "Demain, l'humidité sera de " << response.humidity_percent << "%, "; + ss << "la vitesse du vent sera de " << response.wind_speed_kph << " kilomètres par heure, "; } else { @@ -94,11 +106,20 @@ string WeatherForecastState::generateFrenchText(const string& _) return ss.str(); } -void WeatherForecastState::getLocalWeatherForecast(bool& ok, cloud_data::LocalWeatherForecast& srv) +void WeatherForecastState::getLocalWeatherForecast(bool& ok, cloud_data::srv::LocalWeatherForecast::Response& response) { - ros::ServiceClient service = - m_nodeHandle.serviceClient("cloud_data/local_weather_forecast"); + auto request = make_shared(); + request->relative_day = 1; // tomorow - srv.request.relative_day = 1; // tomorow - ok = service.exists() && service.call(srv); + auto future = m_weatherClient->async_send_request(request); + auto status = future.wait_for(WEATHER_SERVICE_TIMEOUT); + if (status == future_status::ready) + { + response = *future.get(); + ok = response.ok; + } + else + { + ok = false; + } } diff --git a/ros/demos/smart_speaker/src/states/task/WeatherForecastState.h b/ros/demos/smart_speaker/src/states/task/WeatherForecastState.h index 26987f94..af346131 100644 --- a/ros/demos/smart_speaker/src/states/task/WeatherForecastState.h +++ b/ros/demos/smart_speaker/src/states/task/WeatherForecastState.h @@ -3,17 +3,19 @@ #include "../common/TalkState.h" -#include -#include +#include class WeatherForecastState : public TalkState { + rclcpp::CallbackGroup::SharedPtr m_weatherClientCallbackGroup; + rclcpp::Client::SharedPtr m_weatherClient; + public: WeatherForecastState( Language language, StateManager& stateManager, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + rclcpp::Node::SharedPtr node, std::type_index nextStateType); ~WeatherForecastState() override = default; @@ -27,7 +29,7 @@ class WeatherForecastState : public TalkState std::string generateFrenchText(const std::string& _) override; private: - void getLocalWeatherForecast(bool& ok, cloud_data::LocalWeatherForecast& srv); + void getLocalWeatherForecast(bool& ok, cloud_data::srv::LocalWeatherForecast::Response& response); }; inline std::type_index WeatherForecastState::type() const diff --git a/ros/demos/t_top_opentera/CMakeLists.txt b/ros/demos/t_top_opentera/CMakeLists.txt index 242895e5..0c4d49cd 100644 --- a/ros/demos/t_top_opentera/CMakeLists.txt +++ b/ros/demos/t_top_opentera/CMakeLists.txt @@ -1,215 +1,53 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.8) project(t_top_opentera) -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - hbba_lite - roscpp - sensor_msgs - std_msgs - t_top_hbba_lite - opentera_webrtc_ros_msgs - opentera_webrtc_ros - map_image_generator - led_animations - daemon_ros_client -) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -# add_message_files( -# FILES -# Message1.msg -# Message2.msg -# ) +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) +find_package(ament_cmake REQUIRED) -## Generate added messages and services with any dependencies listed here -# generate_messages( -# DEPENDENCIES -# sensor_msgs# std_msgs -# ) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( - # INCLUDE_DIRS include - # LIBRARIES smart_speaker - # CATKIN_DEPENDS audio_analyzer cloud_data gesture hbba_lite person_identification roscpp sensor_msgs std_msgs talk video_analyzer - # DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( - # include - ${catkin_INCLUDE_DIRS} -) +find_package(rclcpp REQUIRED) -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/smart_speaker.cpp -# ) +find_package(std_srvs REQUIRED) +find_package(opentera_webrtc_ros_msgs REQUIRED) -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) +find_package(t_top_hbba_lite REQUIRED) -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide add_executable(${PROJECT_NAME}_node src/${PROJECT_NAME}_node.cpp ) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -add_dependencies(${PROJECT_NAME}_node ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -target_link_libraries(${PROJECT_NAME}_node - ${catkin_LIBRARIES} - ) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -# catkin_install_python(PROGRAMS -# scripts/my_python_script -# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_smart_speaker.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() - -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +target_include_directories(${PROJECT_NAME}_node PRIVATE src) +ament_target_dependencies(${PROJECT_NAME}_node + rclcpp + std_srvs + t_top_hbba_lite + opentera_webrtc_ros_msgs +) +install(TARGETS ${PROJECT_NAME}_node DESTINATION lib/${PROJECT_NAME}) + +install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}) + +if(BUILD_TESTING) + find_package(ament_lint_auto REQUIRED) + # the following line skips the linter which checks for copyrights + # comment the line when a copyright and license is added to all source files + set(ament_cmake_copyright_FOUND TRUE) + # the following line skips cpplint (only works in a git repo) + # comment the line when this package is in a git repo and when + # a copyright and license is added to all source files + set(ament_cmake_cpplint_FOUND TRUE) + ament_lint_auto_find_test_dependencies() +endif() + +ament_package() diff --git a/ros/demos/t_top_opentera/README.md b/ros/demos/t_top_opentera/README.md index b858f525..aa3faf65 100644 --- a/ros/demos/t_top_opentera/README.md +++ b/ros/demos/t_top_opentera/README.md @@ -5,8 +5,9 @@ This folder contains a node that makes T-Top a telepresence robot using OpenTera ## Installation 1. Follow the installation guide for [T-Top](../../../documentation/assembly/01_COMPUTER_CONFIGURATION.md) dependencies. -2. Install the requirements for OpenTera from the [system](../../opentera-webrtc-ros/README.md#Requirements) and for [Python](../../opentera-webrtc-ros/README.md#3---Install-the-Python-requirements). -3. Build the ROS workspace using `catkin_make`. +2. Clone the [opentera-webrtc-ros](https://github.com/introlab/opentera-webrtc-ros) repository in the workspace. +3. Install the requirements for OpenTera from the [system](../../../../opentera-webrtc-ros/README.md#Requirements) and for [Python](../../../../opentera-webrtc-ros/README.md#3---Install-the-Python-requirements). +4. Build the ROS workspace using `colcon build`. ## How to Launch The OpenTera telepresence stack can be launched in stand-alone mode or using the OpenTera servers. @@ -17,7 +18,7 @@ To launch in stand-alone mode, you will need to generate CA certificates and key 1. Start the ROS stack. ```bash export DISPLAY=:0.0 -roslaunch t_top_opentera t_top_opentera.launch +ros2 launch t_top_opentera t_top_opentera.launch.xml ``` 2. On your developpement machine, navigate to `https://:8080/index.html#/user?pwd=abc&robot=TTOP`, where `` is the IP address of your robot on the LAN. @@ -28,14 +29,14 @@ To launch using the OpenTera servers, you will need to configure the OpenTera se 2. Copy the template config file to the destination: ```bash mkdir -p ~/.ros/opentera -cp $(rospack find opentera_client_ros)/config/client_config.json ~/.ros/opentera/client_config.json +cp $(ros2 pkg prefix --share opentera_client_ros)/config/client_config.json ~/.ros/opentera/client_config.json ``` 3. Edit the file `~/.ros/opentera/client_config.json` to set the token and url to the token from step 1 and `https://telesante.3it.usherbrooke.ca:40075`, respectively. 1. Start the ROS stack. ```bash export DISPLAY=:0.0 -roslaunch t_top_opentera t_top_opentera_online.launch +ros2 launch t_top_opentera t_top_opentera_online.launch.xml ``` 2. On your developpement machine, navigate to `https://telesante.3it.usherbrooke.ca:40075/robot/#/login`. diff --git a/ros/demos/t_top_opentera/launch/t_top_opentera.launch b/ros/demos/t_top_opentera/launch/t_top_opentera.launch deleted file mode 100644 index 57044dec..00000000 --- a/ros/demos/t_top_opentera/launch/t_top_opentera.launch +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/ros/demos/t_top_opentera/launch/t_top_opentera.launch.xml b/ros/demos/t_top_opentera/launch/t_top_opentera.launch.xml new file mode 100644 index 00000000..addcc59b --- /dev/null +++ b/ros/demos/t_top_opentera/launch/t_top_opentera.launch.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/ros/demos/t_top_opentera/launch/t_top_opentera_online.launch b/ros/demos/t_top_opentera/launch/t_top_opentera_online.launch deleted file mode 100644 index a1649c82..00000000 --- a/ros/demos/t_top_opentera/launch/t_top_opentera_online.launch +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/ros/demos/t_top_opentera/launch/t_top_opentera_online.launch.xml b/ros/demos/t_top_opentera/launch/t_top_opentera_online.launch.xml new file mode 100644 index 00000000..e9df92e2 --- /dev/null +++ b/ros/demos/t_top_opentera/launch/t_top_opentera_online.launch.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/ros/demos/t_top_opentera/package.xml b/ros/demos/t_top_opentera/package.xml index 097e17e2..fd98020e 100644 --- a/ros/demos/t_top_opentera/package.xml +++ b/ros/demos/t_top_opentera/package.xml @@ -1,89 +1,25 @@ - + + t_top_opentera 0.0.0 The t_top_opentera package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rclcpp - - - - TODO + std_srvs + opentera_webrtc_ros_msgs + t_top_hbba_lite - - - - + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - hbba_lite - roscpp - sensor_msgs - std_msgs - t_top_hbba_lite - opentera_webrtc_ros_msgs - opentera_webrtc_ros - map_image_generator - led_animations - daemon_ros_client - hbba_lite - roscpp - sensor_msgs - std_msgs - t_top_hbba_lite - opentera_webrtc_ros_msgs - opentera_webrtc_ros - map_image_generator - led_animations - daemon_ros_client - hbba_lite - roscpp - sensor_msgs - std_msgs - t_top_hbba_lite - opentera_webrtc_ros_msgs - opentera_webrtc_ros - map_image_generator - led_animations - daemon_ros_client - - - - - + ament_cmake diff --git a/ros/demos/t_top_opentera/src/t_top_opentera_node.cpp b/ros/demos/t_top_opentera/src/t_top_opentera_node.cpp index de4ac2fd..2ca1538a 100644 --- a/ros/demos/t_top_opentera/src/t_top_opentera_node.cpp +++ b/ros/demos/t_top_opentera/src/t_top_opentera_node.cpp @@ -3,128 +3,151 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include +#include -using namespace std; +#include "utils.h" constexpr bool WAIT_FOR_SERVICE = true; class Node { public: - explicit Node(ros::NodeHandle& nodeHandle); - ~Node() = default; + Node(); - static void run() { ros::spin(); } + void run() + { + rclcpp::executors::MultiThreadedExecutor executor(rclcpp::ExecutorOptions(), 2); + executor.add_node(m_node); + executor.spin(); + } + + rclcpp::Logger get_logger() const { return m_node->get_logger(); } private: - ros::NodeHandle& m_nodeHandle; + std::shared_ptr m_node; std::shared_ptr m_desireSet; std::shared_ptr m_filterPool; std::unique_ptr m_hbbaLite; - optional m_activeMovementModeId; + std::optional m_activeMovementModeId; - ros::ServiceServer m_setMovementModeService; - ros::ServiceServer m_listActiveStrategiesService; - ros::ServiceServer m_listActiveDesiresService; + rclcpp::Service::SharedPtr m_setMovementModeService; + rclcpp::Service::SharedPtr m_listActiveStrategiesService; + rclcpp::Service::SharedPtr m_listActiveDesiresService; - bool listActiveStrategiesCb(std_srvs::SetBool::Request& request, std_srvs::SetBool::Response& response); - bool listActiveDesiresCb(std_srvs::SetBool::Request& request, std_srvs::SetBool::Response& response); + void listActiveStrategiesCb( + const std_srvs::srv::SetBool::Request::ConstSharedPtr& request, + const std_srvs::srv::SetBool::Response::SharedPtr& response); + void listActiveDesiresCb( + const std_srvs::srv::SetBool::Request::ConstSharedPtr& request, + const std_srvs::srv::SetBool::Response::SharedPtr& response); - bool setMovementModeCb( - opentera_webrtc_ros_msgs::SetString::Request& request, - opentera_webrtc_ros_msgs::SetString::Response& response); + void setMovementModeCb( + const opentera_webrtc_ros_msgs::srv::SetString::Request::ConstSharedPtr& request, + const opentera_webrtc_ros_msgs::srv::SetString::Response::SharedPtr& response); template void setMovementModeDesire(); + + std::vector> makeStrategies(); }; -Node::Node(ros::NodeHandle& nodeHandle) - : m_nodeHandle{nodeHandle}, - m_desireSet{make_shared()}, - m_filterPool{make_shared(nodeHandle, WAIT_FOR_SERVICE)} +std::vector> Node::makeStrategies() { - vector> strategies; + std::vector> strategies; + strategies.emplace_back(createTelepresenceStrategy(m_filterPool)); strategies.emplace_back(createTeleoperationStrategy(m_filterPool)); strategies.emplace_back(createSoundFollowingStrategy(m_filterPool)); strategies.emplace_back(createNearestFaceFollowingStrategy(m_filterPool)); - m_hbbaLite = make_unique( - m_desireSet, - move(strategies), - std::unordered_map{{"sound", 1}}, - make_unique()); + return strategies; +} - auto telepresenceDesire = make_unique(); +Node::Node() + : m_node{std::make_shared("t_top_opentera_node")}, + m_desireSet{std::make_shared()}, + m_filterPool{std::make_shared(m_node, WAIT_FOR_SERVICE)}, + m_hbbaLite{std::make_unique( + m_desireSet, + makeStrategies(), + std::unordered_map{{"sound", 1}}, + std::make_unique())}, + m_activeMovementModeId{}, + m_setMovementModeService{m_node->create_service( + "set_movement_mode", + bind_this(this, &Node::setMovementModeCb))}, + m_listActiveStrategiesService{m_node->create_service( + "hbba/list_active_strategies", + bind_this(this, &Node::listActiveStrategiesCb))}, + m_listActiveDesiresService{m_node->create_service( + "hbba/list_active_desires", + bind_this(this, &Node::listActiveDesiresCb))} +{ + auto telepresenceDesire = std::make_unique(); m_desireSet->addDesire(std::move(telepresenceDesire)); setMovementModeDesire(); +} - m_setMovementModeService = m_nodeHandle.advertiseService("set_movement_mode", &Node::setMovementModeCb, this); - - m_listActiveStrategiesService = - m_nodeHandle.advertiseService("hbba/list_active_strategies", &Node::listActiveStrategiesCb, this); - m_listActiveDesiresService = - m_nodeHandle.advertiseService("hbba/list_active_desires", &Node::listActiveDesiresCb, this); -}; - -bool Node::listActiveStrategiesCb(std_srvs::SetBool::Request& request, std_srvs::SetBool::Response& response) +void Node::listActiveStrategiesCb( + [[maybe_unused]] const std_srvs::srv::SetBool::Request::ConstSharedPtr& request, + const std_srvs::srv::SetBool::Response::SharedPtr& response) { - response.message = ""; - response.success = true; + response->message = ""; + response->success = true; for (const auto& strategy : m_hbbaLite->getActiveStrategies()) { - response.message += strategy + ";"; + response->message += strategy + ";"; } - - return true; } -bool Node::listActiveDesiresCb(std_srvs::SetBool::Request& request, std_srvs::SetBool::Response& response) +void Node::listActiveDesiresCb( + [[maybe_unused]] const std_srvs::srv::SetBool::Request::ConstSharedPtr& request, + const std_srvs::srv::SetBool::Response::SharedPtr& response) { - response.message = ""; - response.success = true; + response->message = ""; + response->success = true; for (const auto& desire : m_hbbaLite->getActiveDesireNames()) { - response.message += desire + ";"; + response->message += desire + ";"; } - - return true; } -bool Node::setMovementModeCb( - opentera_webrtc_ros_msgs::SetString::Request& request, - opentera_webrtc_ros_msgs::SetString::Response& response) +void Node::setMovementModeCb( + const opentera_webrtc_ros_msgs::srv::SetString::Request::ConstSharedPtr& request, + const opentera_webrtc_ros_msgs::srv::SetString::Response::SharedPtr& response) { - response.message = ""; - response.success = true; + response->success = false; + response->message = "Unknown movement mode"; + + const auto set_success = [&response]() + { + response->message = ""; + response->success = true; + }; - if (request.data == "teleop") + if (request->data == "teleop") { setMovementModeDesire(); + set_success(); } - else if (request.data == "sound") + else if (request->data == "sound") { setMovementModeDesire(); + set_success(); } - else if (request.data == "face") + else if (request->data == "face") { setMovementModeDesire(); + set_success(); } - else - { - response.success = false; - response.message = "Unknown movement mode"; - } - - return true; } template @@ -136,19 +159,25 @@ void Node::setMovementModeDesire() m_desireSet->removeDesire(m_activeMovementModeId.value()); } - auto movementModeDesire = make_unique(); + auto movementModeDesire = std::make_unique(); m_activeMovementModeId = movementModeDesire->id(); m_desireSet->addDesire(std::move(movementModeDesire)); } int main(int argc, char** argv) { - ros::init(argc, argv, "t_top_opentera_node"); - ros::NodeHandle nodeHandle; - ros::NodeHandle privateNodeHandle("~"); + rclcpp::init(argc, argv); - Node node{nodeHandle}; - Node::run(); + Node node; + + try + { + node.run(); + } + catch (const std::exception& e) + { + RCLCPP_ERROR_STREAM(node.get_logger(), "T-Top OpenTera Node crashed (" << e.what() << ")"); + } return 0; } diff --git a/ros/demos/t_top_opentera/src/utils.h b/ros/demos/t_top_opentera/src/utils.h new file mode 100644 index 00000000..54752ccb --- /dev/null +++ b/ros/demos/t_top_opentera/src/utils.h @@ -0,0 +1,55 @@ +#ifndef UTILS_H +#define UTILS_H + +#include +#include + +namespace details +{ + template + struct has_request_type : std::false_type + { + }; + + template + struct has_request_type> : std::true_type + { + }; + + + template + struct has_response_type : std::false_type + { + }; + + template + struct has_response_type> : std::true_type + { + }; + + template + struct has_request_response_types : std::conjunction, has_response_type> + { + }; +} + +template +inline auto bind_this(This* self, Func&& func) -> std::enable_if_t< + !details::has_request_response_types::value, + std::function> +{ + return [self, func](const typename MessageT::SharedPtr msg) { (self->*func)(msg); }; +} + +template +inline auto bind_this(This* self, Func&& func) + -> std::enable_if_t< + details::has_request_response_types::value, + std::function> +{ + return + [self, func](const typename MessageT::Request::SharedPtr req, const typename MessageT::Response::SharedPtr res) + { (self->*func)(req, res); }; +} + +#endif diff --git a/ros/opentera-webrtc-ros b/ros/opentera-webrtc-ros deleted file mode 160000 index 1df7ee0c..00000000 --- a/ros/opentera-webrtc-ros +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 1df7ee0cb2a1589703cf08d59f1b3a52779e186f diff --git a/ros/perceptions/audio_analyzer/CMakeLists.txt b/ros/perceptions/audio_analyzer/CMakeLists.txt index 00ad2178..c314321f 100644 --- a/ros/perceptions/audio_analyzer/CMakeLists.txt +++ b/ros/perceptions/audio_analyzer/CMakeLists.txt @@ -1,212 +1,37 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(audio_analyzer) -## Compile as C++11, supported in ROS Kinetic and newer -# add_compile_options(-std=c++11) - -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - dnn_utils - rospy - std_msgs - message_generation - message_filters - sensor_msgs - odas_ros - audio_utils - hbba_lite -) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -add_message_files( - FILES - AudioAnalysis.msg -) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -generate_messages( - DEPENDENCIES - std_msgs - audio_utils -) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( -# INCLUDE_DIRS include -# LIBRARIES audio_analyzer - CATKIN_DEPENDS dnn_utils rospy std_msgs message_runtime -# DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( -# include - ${catkin_INCLUDE_DIRS} -) - -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/audio_analyzer.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -# add_executable(${PROJECT_NAME}_node src/audio_analyzer_node.cpp) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -# target_link_libraries(${PROJECT_NAME}_node -# ${catkin_LIBRARIES} -# ) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -catkin_install_python(PROGRAMS +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclpy REQUIRED) +find_package(std_msgs REQUIRED) +find_package(sensor_msgs REQUIRED) +find_package(odas_ros_msgs REQUIRED) +find_package(audio_utils_msgs REQUIRED) +find_package(hbba_lite REQUIRED) +find_package(perception_msgs REQUIRED) + +# Python Nodes +install(PROGRAMS scripts/audio_analyzer_node.py - DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} + DESTINATION lib/${PROJECT_NAME} ) -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_audio_analyzer.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() +# Launch files +install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}) -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/perceptions/audio_analyzer/README.md b/ros/perceptions/audio_analyzer/README.md index 0af94f19..74713197 100644 --- a/ros/perceptions/audio_analyzer/README.md +++ b/ros/perceptions/audio_analyzer/README.md @@ -6,17 +6,17 @@ This folder contains the node to analyze the audio. This node classifies the audio and extracts a general audio embedding. If the audio contains a voice, it extracts a voice embedding. #### Parameters - - `inference_type` (string): Indicates where to run the neural network (cpu, torch_gpu or trt_gpu). - - `interval` (int): The interval between inferences in sample (low_quality_audio_in). - - `voice_probability_threshold` (double): The voice probability threshold for the voice embedding. - - `class_probability_threshold` (double): The class probability threshold for the audio analysis. + - `inference_type` (string): Indicates where to run the neural network (cpu, torch_gpu or trt_gpu). The default value is `cpu`. + - `interval` (int): The interval between inferences in sample (low_quality_audio_in). The default value is 16000. + - `voice_probability_threshold` (double): The voice probability threshold for the voice embedding. The default value is 0.5. + - `class_probability_threshold` (double): The class probability threshold for the audio analysis. The default value is 0.5. #### Subscribed Topics - - `audio_in` ([audio_utils/AudioFrame](https://github.com/introlab/audio_utils/blob/main/msg/AudioFrame.msg)): The sound topic processed, which must be signed_16, at 16000 Hz and 1 channel. - - `sst` ([odas_ros/OdasSstArrayStamped](https://github.com/introlab/odas_ros/blob/main/msg/OdasSstArrayStamped.msg)): The sound source tracking information. + - `audio_in` ([audio_utils_msgs/AudioFrame](https://github.com/introlab/audio_utils/blob/ros2/audio_utils_msgs/msg/AudioFrame.msg)): The sound topic processed, which must be signed_16, at 16000 Hz and 1 channel. + - `sst` ([odas_ros_msgs/OdasSstArrayStamped](https://github.com/introlab/odas_ros/blob/ros2/odas_ros_msgs/msg/OdasSstArrayStamped.msg)): The sound source tracking information. #### Published Topics - - `audio_analysis` ([audio_analyzer/AudioAnalysis](msg/AudioAnalysis.msg)): The audio analysis containing the audio classes, general audio embedding, voice embedding and the sound direction. + - `audio_analysis` ([perception_msgs/AudioAnalysis](../perception_msgs/msg/AudioAnalysis.msg)): The audio analysis containing the audio classes, general audio embedding, voice embedding and the sound direction. #### Services - - `audio_in/filter_state` ([hbba_lite/SetOnOffFilterState](../../hbba_lite/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the processing. + - `audio_in/filter_state` ([hbba_lite_srvs/SetOnOffFilterState](../../utils/hbba_lite/hbba_lite_srvs/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the processing. diff --git a/ros/t_top/launch/tests/test_audio_analyzer.launch b/ros/perceptions/audio_analyzer/launch/test_audio_analyzer.launch.xml similarity index 63% rename from ros/t_top/launch/tests/test_audio_analyzer.launch rename to ros/perceptions/audio_analyzer/launch/test_audio_analyzer.launch.xml index fc0174c8..2eeafcd0 100644 --- a/ros/t_top/launch/tests/test_audio_analyzer.launch +++ b/ros/perceptions/audio_analyzer/launch/test_audio_analyzer.launch.xml @@ -1,28 +1,26 @@ - + - + - - - - + + + - diff --git a/ros/perceptions/audio_analyzer/package.xml b/ros/perceptions/audio_analyzer/package.xml index e32cd5ad..2aadd205 100644 --- a/ros/perceptions/audio_analyzer/package.xml +++ b/ros/perceptions/audio_analyzer/package.xml @@ -1,79 +1,30 @@ - + + audio_analyzer 0.0.0 The audio_analyzer package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rclpy + dnn_utils + std_msgs + sensor_msgs + odas_ros_msgs + audio_utils_msgs + hbba_lite + perception_msgs - - - - TODO + rosidl_default_runtime + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - dnn_utils - rospy - std_msgs - message_generation - odas_ros - audio_utils - hbba_lite - dnn_utils - rospy - std_msgs - odas_ros - audio_utils - hbba_lite - dnn_utils - rospy - std_msgs - message_runtime - odas_ros - audio_utils - hbba_lite - - - - - + ament_cmake diff --git a/ros/perceptions/audio_analyzer/scripts/audio_analyzer_node.py b/ros/perceptions/audio_analyzer/scripts/audio_analyzer_node.py index f14c498a..ce63fc66 100755 --- a/ros/perceptions/audio_analyzer/scripts/audio_analyzer_node.py +++ b/ros/perceptions/audio_analyzer/scripts/audio_analyzer_node.py @@ -6,12 +6,12 @@ import torch -import rospy -from std_msgs.msg import Bool +import rclpy +import rclpy.node -from audio_utils.msg import AudioFrame -from audio_analyzer.msg import AudioAnalysis -from odas_ros.msg import OdasSstArrayStamped +from audio_utils_msgs.msg import AudioFrame +from perception_msgs.msg import AudioAnalysis +from odas_ros_msgs.msg import OdasSstArrayStamped from dnn_utils import MulticlassAudioDescriptorExtractor, VoiceDescriptorExtractor import hbba_lite @@ -21,9 +21,11 @@ SUPPORTED_CHANNEL_COUNT = 1 -class AudioAnalyzerNode: +class AudioAnalyzerNode(rclpy.node.Node): def __init__(self): - self._inference_type = rospy.get_param('~inference_type', None) + super().__init__('audio_analyzer_node') + + self._inference_type = self.declare_parameter('inference_type', 'cpu').get_parameter_value().string_value self._audio_descriptor_extractor = MulticlassAudioDescriptorExtractor(inference_type=self._inference_type) self._voice_descriptor_extractor = VoiceDescriptorExtractor(inference_type=self._inference_type) @@ -32,9 +34,9 @@ def __init__(self): raise ValueError('Not compatible models (sampling frequency)') self._supported_sampling_frequency = self._audio_descriptor_extractor.get_supported_sampling_frequency() - self._audio_analysis_interval = rospy.get_param('~interval') - self._voice_probability_threshold = rospy.get_param('~voice_probability_threshold') - self._class_probability_threshold = rospy.get_param('~class_probability_threshold') + self._audio_analysis_interval = self.declare_parameter('interval', 16000).get_parameter_value().integer_value + self._voice_probability_threshold = self.declare_parameter('voice_probability_threshold', 0.5).get_parameter_value().double_value + self._class_probability_threshold = self.declare_parameter('class_probability_threshold', 0.5).get_parameter_value().double_value self._audio_buffer_duration = max(self._audio_descriptor_extractor.get_supported_duration(), self._voice_descriptor_extractor.get_supported_duration(), @@ -50,21 +52,20 @@ def __init__(self): self._audio_direction_lock = threading.Lock() self._audio_direction = ('', 0.0, 0.0, 0.0) - self._audio_analysis_pub = rospy.Publisher('audio_analysis', AudioAnalysis, queue_size=10) - self._audio_analysis_seq = 0 + self._audio_analysis_pub = self.create_publisher(AudioAnalysis, 'audio_analysis', 10) self._sst_id = -1 - self._hbba_filter_state = hbba_lite.OnOffHbbaFilterState('audio_in/filter_state') - self._audio_sub = rospy.Subscriber('audio_in', AudioFrame, self._audio_cb, queue_size=100) + self._hbba_filter_state = hbba_lite.OnOffHbbaFilterState(self, 'audio_in/filter_state') + self._audio_sub = self.create_subscription(AudioFrame, 'audio_in', self._audio_cb, 100) - self._sst_sub = rospy.Subscriber('sst', OdasSstArrayStamped, self._sst_cb, queue_size=10) + self._sst_sub = self.create_subscription(OdasSstArrayStamped, 'sst', self._sst_cb, 1) def _audio_cb(self, msg): if msg.format != SUPPORTED_AUDIO_FORMAT or \ msg.channel_count != SUPPORTED_CHANNEL_COUNT or \ msg.sampling_frequency != self._supported_sampling_frequency: - rospy.logerr('Invalid audio frame (msg.format={}, msg.channel_count={}, msg.sampling_frequency={}})' + self.get_logger().error('Invalid audio frame (msg.format={}, msg.channel_count={}, msg.sampling_frequency={}})' .format(msg.format, msg.channel_count, msg.sampling_frequency)) return if self._hbba_filter_state.is_filtering_all_messages: @@ -88,16 +89,18 @@ def _audio_cb(self, msg): def _analyse(self): start_time = datetime.now() audio_buffer, sst_id = self._get_audio_buffer_and_sst_id() + if audio_buffer.size()[0] < self._audio_buffer_duration: + self._publish_audio_analysis(sst_id, audio_buffer, [], [], []) + return + audio_descriptor_buffer = audio_buffer[-self._audio_descriptor_extractor.get_supported_duration():] audio_descriptor, audio_class_probabilities = self._audio_descriptor_extractor(audio_descriptor_buffer) audio_descriptor = audio_descriptor.tolist() - print('Voice prob:', audio_class_probabilities[self._voice_class_index].item()) + voice_descriptor = [] if audio_class_probabilities[self._voice_class_index].item() >= self._voice_probability_threshold: voice_descriptor_buffer = audio_buffer[-self._voice_descriptor_extractor.get_supported_duration():] voice_descriptor = self._voice_descriptor_extractor(voice_descriptor_buffer).tolist() - else: - voice_descriptor = [] audio_classes = self._get_audio_classes(audio_class_probabilities) processing_time_s = (datetime.now() - start_time).total_seconds() @@ -108,7 +111,7 @@ def _get_audio_buffer_and_sst_id(self): sst_id = self._sst_id audio_buffer = torch.cat(self._audio_frames, dim=0) if audio_buffer.size()[0] < self._audio_buffer_duration: - return torch.cat([torch.zeros(self._audio_buffer_duration - audio_buffer.size()[0]), audio_buffer], dim=0), sst_id + return audio_buffer, sst_id else: return audio_buffer[-self._audio_buffer_duration:], sst_id @@ -116,13 +119,15 @@ def _get_audio_classes(self, audio_class_probabilities): return [self._class_names[i] for i in range(len(self._class_names)) if audio_class_probabilities[i].item() >= self._class_probability_threshold] - def _publish_audio_analysis(self, sst_id, audio_buffer, audio_classes, audio_descriptor, voice_descriptor, processing_time_s=0): + def _publish_audio_analysis(self, sst_id, audio_buffer, audio_classes, audio_descriptor, voice_descriptor, processing_time_s=0.0): with self._audio_direction_lock: frame_id, direction_x, direction_y, direction_z = self._audio_direction + if frame_id == '': + return + msg = AudioAnalysis() - msg.header.seq = self._audio_analysis_seq - msg.header.stamp = rospy.Time.now() + msg.header.stamp = self.get_clock().now().to_msg() msg.header.frame_id = frame_id msg.tracking_id = sst_id @@ -144,37 +149,46 @@ def _publish_audio_analysis(self, sst_id, audio_buffer, audio_classes, audio_des msg.processing_time_s = processing_time_s self._audio_analysis_pub.publish(msg) - self._audio_analysis_seq += 1 def _sst_cb(self, sst): if len(sst.sources) == 0: + self._reset_sst(-1) return if len(sst.sources) > 1: - rospy.logerr('Invalid sst (len(sst.sources)={})'.format(len(sst.sources))) + self.get_logger().error('Invalid sst (len(sst.sources)={})'.format(len(sst.sources))) return if sst.sources[0].id != self._sst_id: - print('New source') - self._sst_id = sst.sources[0].id + self._reset_sst(sst.sources[0].id) with self._audio_frames_lock: self._audio_frames = [] with self._audio_direction_lock: self._audio_direction = (sst.header.frame_id, sst.sources[0].x, sst.sources[0].y, sst.sources[0].z) + def _reset_sst(self, new_sst_id): + self._sst_id = new_sst_id + with self._audio_frames_lock: + self._audio_frames = [] + def run(self): - rospy.spin() + rclpy.spin(self) def main(): - rospy.init_node('audio_analyzer_node') + rclpy.init() audio_analyzer_node = AudioAnalyzerNode() - audio_analyzer_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + audio_analyzer_node.run() + except KeyboardInterrupt: pass + finally: + audio_analyzer_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/perceptions/ego_noise_reduction/CMakeLists.txt b/ros/perceptions/ego_noise_reduction/CMakeLists.txt index 0e6804ca..45ae594a 100644 --- a/ros/perceptions/ego_noise_reduction/CMakeLists.txt +++ b/ros/perceptions/ego_noise_reduction/CMakeLists.txt @@ -1,127 +1,34 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(ego_noise_reduction) -## Compile as C++11, supported in ROS Kinetic and newer -# add_compile_options(-std=c++11) -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - audio_utils - roscpp - rospy - std_msgs - hbba_lite - t_top - daemon_ros_client -) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -# add_message_files( -# FILES -# Message1.msg -# Message2.msg -# ) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -# generate_messages( -# DEPENDENCIES -# std_msgs -# ) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( -# INCLUDE_DIRS include -# LIBRARIES ego_noise_reduction -# CATKIN_DEPENDS audio_utils roscpp rospy std_msgs -# DEPENDS system_lib -) +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() -########### -## Build ## -########### +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() -## Specify additional locations of header files -## Your package locations should be listed before other locations +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclcpp REQUIRED) +find_package(rclpy REQUIRED) +find_package(audio_utils REQUIRED) +find_package(std_msgs REQUIRED) +find_package(hbba_lite REQUIRED) +find_package(t_top REQUIRED) +find_package(daemon_ros_client REQUIRED) + +# C++ Library include_directories( include - ${catkin_INCLUDE_DIRS} ) ## Declare a C++ library @@ -134,103 +41,61 @@ add_library(${PROJECT_NAME} STATIC src/${PROJECT_NAME}/WeightedAverageWithAPrioriNoiseEstimator.cpp src/${PROJECT_NAME}/NoiseMagnitudeDatabase.cpp ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -add_executable(${PROJECT_NAME}_node src/ego_noise_reduction_node.cpp) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -target_link_libraries(${PROJECT_NAME}_node +ament_target_dependencies(${PROJECT_NAME} audio_utils) +target_link_libraries(${PROJECT_NAME} ${audio_utils_LIBRARIES}) +install(DIRECTORY include DESTINATION include) +install(TARGETS ${PROJECT_NAME} DESTINATION lib) + +ament_export_dependencies(rclcpp audio_utils) +ament_export_include_directories(include) +ament_export_libraries(${PROJECT_NAME}) + +# C++ Nodes +add_executable(ego_noise_reduction_node src/ego_noise_reduction_node.cpp) +ament_target_dependencies(ego_noise_reduction_node rclcpp std_msgs daemon_ros_client hbba_lite hbba_lite_srvs audio_utils) +target_link_libraries(ego_noise_reduction_node ${PROJECT_NAME} - ${catkin_LIBRARIES} + ${audio_utils_LIBRARIES} + ${hbba_lite_LIBRARIES} + ${hbba_lite_srvs_LIBRARIES} ) +install(TARGETS ego_noise_reduction_node DESTINATION lib/${PROJECT_NAME}) -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -catkin_install_python(PROGRAMS +# Python Nodes +install(PROGRAMS scripts/data_gathering.py scripts/test.py - DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} + DESTINATION lib/${PROJECT_NAME} ) -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -install(TARGETS ${PROJECT_NAME} - ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} - LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} - RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -) - -## Mark cpp header files for installation -install(DIRECTORY include/${PROJECT_NAME}/ - DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} - FILES_MATCHING PATTERN "*.h" - PATTERN ".svn" EXCLUDE -) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -catkin_add_gtest(${PROJECT_NAME}-test - test/ego_noise_reduction/MathTests.cpp - test/ego_noise_reduction/StftNoiseRemoverTests.cpp - test/ego_noise_reduction/SpectralSubtractionNoiseRemoverTests.cpp - test/ego_noise_reduction/LogMmseNoiseRemoverTests.cpp - test/ego_noise_reduction/NoiseEstimatorTests.cpp - test/ego_noise_reduction/WeightedAverageNoiseEstimatorTests.cpp - test/ego_noise_reduction/WeightedAverageWithAPrioriNoiseEstimatorTests.cpp - test/ego_noise_reduction/NoiseMagnitudeDatabaseTests.cpp - test/ego_noise_reduction/TestUtils.cpp - test/ego_noise_reduction/main.cpp -) -if(TARGET ${PROJECT_NAME}-test) - target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME} ${catkin_LIBRARIES}) +# Launch files +install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}) + +# Noise files +install(DIRECTORY noise_data DESTINATION share/${PROJECT_NAME}) + +# Tests +if(BUILD_TESTING) + find_package(ament_cmake_gtest REQUIRED) + ament_add_gtest(${PROJECT_NAME}_test + test/ego_noise_reduction/MathTests.cpp + test/ego_noise_reduction/StftNoiseRemoverTests.cpp + test/ego_noise_reduction/SpectralSubtractionNoiseRemoverTests.cpp + test/ego_noise_reduction/LogMmseNoiseRemoverTests.cpp + test/ego_noise_reduction/NoiseEstimatorTests.cpp + test/ego_noise_reduction/WeightedAverageNoiseEstimatorTests.cpp + test/ego_noise_reduction/WeightedAverageWithAPrioriNoiseEstimatorTests.cpp + test/ego_noise_reduction/NoiseMagnitudeDatabaseTests.cpp + test/ego_noise_reduction/TestUtils.cpp + test/ego_noise_reduction/main.cpp + ) + ament_target_dependencies(${PROJECT_NAME}_test rclcpp audio_utils) + target_link_libraries(${PROJECT_NAME}_test ${PROJECT_NAME} ${audio_utils_LIBRARIES}) - add_custom_command(TARGET ${PROJECT_NAME}-test POST_BUILD + add_custom_command(TARGET ${PROJECT_NAME}_test POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory - ${PROJECT_SOURCE_DIR}/test/ego_noise_reduction/resources $/resources + ${PROJECT_SOURCE_DIR}/test/ego_noise_reduction/resources $/resources ) endif() -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/perceptions/ego_noise_reduction/README.md b/ros/perceptions/ego_noise_reduction/README.md index 7265eb8d..135603ac 100644 --- a/ros/perceptions/ego_noise_reduction/README.md +++ b/ros/perceptions/ego_noise_reduction/README.md @@ -7,13 +7,14 @@ This node gathers the data needed to perform ego noise reduction. To use this no Use the following command to launch the nodes. ```bash -roslaunch ego_noise_reduction data_gathering.launch +ros2 launch ego_noise_reduction data_gathering.launch ``` #### Parameters - - `n_fft` (int): The FFT frame size. - - `sampling_frequency` (int): The sampling frequency of the audio. - - `channel_count` (int): The channel count of the audio. + - `n_fft` (int): The FFT frame size. The default value is `1024`. + - `sampling_frequency` (int): The sampling frequency of the audio. The default value is `16000`. + - `channel_count` (int): The channel count of the audio. The default value is `16`. + - `audio_queue_size` (int): The audio queue size. The default value is `1`. ### `test.py` This node tests the ego noise reduction. @@ -27,18 +28,18 @@ roslaunch ego_noise_reduction test.launch output_directory:= This node performs ego noise reduction. #### Parameters - - `type` (string): The noise reduction algorithm to use (`spectral_subtraction` or `log_mmse`). - - `format` (string): The audio format (see [audio_utils/AudioFrame](../../audio_utils/msg/AudioFrame.msg)).. - - `channel_count` (int): The channel count of the audio. - - `sampling_frequency` (int): The sampling frequency of the audio. - - `frame_sample_count` (int): The number of samples in each frame. + - `type` (string): The noise reduction algorithm to use (`spectral_subtraction` or `log_mmse`). The default value is `log_mmse`. + - `format` (string): The audio format (see [audio_utils_msgs/AudioFrame](../../utils/audio_utils/audio_utils_msgs/msg/AudioFrame.msg)). The default value is `signed_32`. + - `channel_count` (int): The channel count of the audio. The default value is `16`. + - `sampling_frequency` (int): The sampling frequency of the audio. The default value is `16000`. + - `frame_sample_count` (int): The number of samples in each frame. The default value is `1024`. - `n_fft` (int): The FFT frame size. It must be a multiple of `frame_sample_count`. - `noise_directory` (string): The directory path containing the noise data. - `noise_estimator_epsilon` (double): The sensitivity of the noise estimation algorithm. The default value is `4.0`. - `noise_estimator_alpha` (double): The recursive average of the noise magnitude. The default value is `0.9`. - `noise_estimator_delta` (double): The recursive average of the noise magnitude variance. The default value is `0.9`. - - `spectral_subtraction_alpha0` (double): This parameter is useful when the type `spectral_subtraction`. is The default value is `5.0`. + - `spectral_subtraction_alpha0` (double): This parameter is useful when the type `spectral_subtraction`. The default value is `5.0`. - `spectral_subtraction_gamma` (double): This parameter is useful when the type `spectral_subtraction`. The default value is `0.1`. - `spectral_subtraction_beta` (double): This parameter is useful when the type `spectral_subtraction`. The default value is `0.01`. @@ -48,10 +49,10 @@ This node performs ego noise reduction. #### Subscribed Topics - `daemon/motor_status` ([daemon_ros_client/MotorStatus](../../daemon_ros_client/msg/MotorStatus.msg)): The current motor status. - - `audio_in` ([audio_utils/AudioFrame](https://github.com/introlab/audio_utils/blob/main/msg/AudioFrame.msg)): The sound topic to process. + - `audio_in` ([audio_utils_msgs/AudioFrame](https://github.com/introlab/audio_utils/blob/ros2/audio_utils_msgs/msg/AudioFrame.msg)): The sound topic to process. #### Published Topics -- `audio_out` ([audio_utils/AudioFrame](https://github.com/introlab/audio_utils/blob/main/msg/AudioFrame.msg)): The processed sound topic. +- `audio_out` ([audio_utils_msgs/AudioFrame](https://github.com/introlab/audio_utils/blob/ros2/audio_utils_msgs/msg/AudioFrame.msg)): The processed sound topic. ## Acknowledgments diff --git a/ros/perceptions/ego_noise_reduction/launch/data_gathering.launch b/ros/perceptions/ego_noise_reduction/launch/data_gathering.launch.xml similarity index 71% rename from ros/perceptions/ego_noise_reduction/launch/data_gathering.launch rename to ros/perceptions/ego_noise_reduction/launch/data_gathering.launch.xml index 5dc20b88..51afc4c3 100644 --- a/ros/perceptions/ego_noise_reduction/launch/data_gathering.launch +++ b/ros/perceptions/ego_noise_reduction/launch/data_gathering.launch.xml @@ -1,11 +1,11 @@ - + - + @@ -15,15 +15,12 @@ + - - - [front-left, front-right, rear-left, rear-right, front-center, lfe, side-left, side-right, aux0, aux1, aux2, aux3, aux4, aux5, aux6, aux7] - - + diff --git a/ros/perceptions/ego_noise_reduction/launch/test.launch b/ros/perceptions/ego_noise_reduction/launch/test.launch.xml similarity index 59% rename from ros/perceptions/ego_noise_reduction/launch/test.launch rename to ros/perceptions/ego_noise_reduction/launch/test.launch.xml index bfd75cca..0c2e5332 100644 --- a/ros/perceptions/ego_noise_reduction/launch/test.launch +++ b/ros/perceptions/ego_noise_reduction/launch/test.launch.xml @@ -1,9 +1,9 @@ - + - + @@ -13,45 +13,44 @@ + - - - [front-left, front-right, rear-left, rear-right, front-center, lfe, side-left, side-right, aux0, aux1, aux2, aux3, aux4, aux5, aux6, aux7] - - + - + - + + + - + - - + + - - + + - - + + diff --git a/ros/perceptions/ego_noise_reduction/package.xml b/ros/perceptions/ego_noise_reduction/package.xml index 78e86ddc..e03636d2 100644 --- a/ros/perceptions/ego_noise_reduction/package.xml +++ b/ros/perceptions/ego_noise_reduction/package.xml @@ -1,80 +1,33 @@ - + + ego_noise_reduction 0.0.0 The ego_noise_reduction package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rosidl_default_generators + rclcpp + rclpy - - - - TODO + audio_utils + std_msgs + hbba_lite + t_top + daemon_ros_client + rosidl_default_runtime + ros2launch + rosidl_interface_packages - - - - + ament_lint_auto + ament_lint_common + ament_cmake_gtest - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - audio_utils - roscpp - rospy - std_msgs - hbba_lite - t_top - daemon_ros_client - audio_utils - roscpp - rospy - std_msgs - hbba_lite - t_top - daemon_ros_client - audio_utils - roscpp - rospy - std_msgs - hbba_lite - t_top - daemon_ros_client - - - - - + ament_cmake diff --git a/ros/perceptions/ego_noise_reduction/scripts/data_gathering.py b/ros/perceptions/ego_noise_reduction/scripts/data_gathering.py index 36fda7d7..b6ea4474 100755 --- a/ros/perceptions/ego_noise_reduction/scripts/data_gathering.py +++ b/ros/perceptions/ego_noise_reduction/scripts/data_gathering.py @@ -2,18 +2,18 @@ import os import math -import threading +import time from collections import defaultdict import numpy as np import librosa import scipy.signal -import rospy -import rospkg +import rclpy +import rclpy.node from std_msgs.msg import Float32, Int32, Empty -from audio_utils.msg import AudioFrame +from audio_utils_msgs.msg import AudioFrame STARTUP_DELAY_S = 10. @@ -27,43 +27,44 @@ def sqrt_hann(M): class AudioAnalyser: - def __init__(self, channel_count, n_fft) -> None: + def __init__(self, node, channel_count, n_fft) -> None: + self._node = node self._channel_count = channel_count self._n_fft = n_fft def analyse(self, input_directory, output_directory): - rospy.loginfo('Analysing the torso_servo files') + self._node.get_logger().info('Analysing the torso_servo files') self._analyze_specific_type(input_directory, output_directory, 'torso_servo') - rospy.loginfo('Analysing the head_servo_id1 files') + self._node.get_logger().info('Analysing the head_servo_id1 files') self._analyze_specific_type(input_directory, output_directory, 'head_servo_id1') - rospy.loginfo('Analysing the head_servo_id2 files') + self._node.get_logger().info('Analysing the head_servo_id2 files') self._analyze_specific_type(input_directory, output_directory, 'head_servo_id2') - rospy.loginfo('Analysing the head_servo_id3 files') + self._node.get_logger().info('Analysing the head_servo_id3 files') self._analyze_specific_type(input_directory, output_directory, 'head_servo_id3') - rospy.loginfo('Analysing the head_servo_id4 files') + self._node.get_logger().info('Analysing the head_servo_id4 files') self._analyze_specific_type(input_directory, output_directory, 'head_servo_id4') - rospy.loginfo('Analysing the head_servo_id5 files') + self._node.get_logger().info('Analysing the head_servo_id5 files') self._analyze_specific_type(input_directory, output_directory, 'head_servo_id5') - rospy.loginfo('Analysing the head_servo_id6 files') + self._node.get_logger().info('Analysing the head_servo_id6 files') self._analyze_specific_type(input_directory, output_directory, 'head_servo_id6') def _analyze_specific_type(self, input_directory, output_directory, prefix): paths_by_speed = self._list_paths_by_speed(input_directory, prefix) paths_by_speed_orientation = self._list_paths_by_speed_orientation(input_directory, prefix) - rospy.loginfo('\tCalculating base noise magnitudes') + self._node.get_logger().info('\tCalculating base noise magnitudes') base_noise_magnitudes_by_speed = self._get_base_noise_magnitudes(paths_by_speed) - rospy.loginfo('\tCalculating orientation tf') + self._node.get_logger().info('\tCalculating orientation tf') orientation_tf = self._get_orientation_tf(paths_by_speed_orientation, base_noise_magnitudes_by_speed) - rospy.loginfo('\tCalculating channel tf') + self._node.get_logger().info('\tCalculating channel tf') channel_tf = self._get_channel_tf(paths_by_speed_orientation, base_noise_magnitudes_by_speed, orientation_tf) self._write_dict_of_array(base_noise_magnitudes_by_speed, @@ -105,7 +106,7 @@ def _stft(self, x): def _get_base_noise_magnitudes(self, paths_by_speed): stfts_by_speed = defaultdict(list) for i, (speed, paths) in enumerate(paths_by_speed.items()): - rospy.loginfo(f'\t\t{i+1}/{len(paths_by_speed)}') + self._node.get_logger().info(f'\t\t{i+1}/{len(paths_by_speed)}') for path in paths: x = self._load_raw_audio_file(path) for c in range(x.shape[1]): @@ -182,22 +183,22 @@ def _write_dict_of_array(self, dict_of_array, path): file.write(' '.join(map(str, value))) file.write('\n') -class DataGatheringNode: +class DataGatheringNode(rclpy.node.Node): def __init__(self): + super().__init__('data_gathering') + self._torso_orientation_deg = 0 self._moving_servo_id = 0 self._moving_servo_speed = 0 self._is_head_servo_audio_recording = False self._is_torso_servo_audio_recording = False - self._lock = threading.Lock() - self._n_fft = rospy.get_param('~n_fft') - self._sampling_frequency = rospy.get_param('~sampling_frequency') - self._channel_count = rospy.get_param('~channel_count') + self._n_fft = self.declare_parameter('n_fft', 1024).get_parameter_value().integer_value + self._sampling_frequency = self.declare_parameter('sampling_frequency', 16000).get_parameter_value().integer_value + self._channel_count = self.declare_parameter('channel_count', 16).get_parameter_value().integer_value self._audio_analyzer = AudioAnalyser(self._channel_count, self._n_fft) - self._rospack = rospkg.RosPack() - self._pkg_path = self._rospack.get_path('ego_noise_reduction') + self._pkg_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..') self._audio_data_directory_path = os.path.join(self._pkg_path, 'audio_data') self._noise_data_directory_path = os.path.join(self._pkg_path, 'noise_data') @@ -206,29 +207,29 @@ def __init__(self): self._write_noise_data_info() - self._start_ego_noise_data_gathering_pub = rospy.Publisher('opencr/start_ego_noise_data_gathering', Empty, queue_size=10) + self._start_ego_noise_data_gathering_pub = self.create_publisher(Empty, 'opencr/start_ego_noise_data_gathering', 10) - self._current_torso_orientation_sub = rospy.Subscriber('opencr/current_torso_orientation', Float32, - self._current_torso_orientation_cb, queue_size=10) - self._moving_servo_id_sub = rospy.Subscriber('opencr/moving_servo_id', Int32, - self._moving_servo_id_cb, queue_size=10) - self._moving_servo_speed = rospy.Subscriber('opencr/moving_servo_speed', Int32, - self._moving_servo_speed_cb, queue_size=10) + self._current_torso_orientation_sub = self.create_subscription(Float32, 'opencr/current_torso_orientation', + self._current_torso_orientation_cb, 10) + self._moving_servo_id_sub = self.create_subscription(Int32, 'opencr/moving_servo_id', + self._moving_servo_id_cb, 10) + self._moving_servo_speed = self.create_subscription(Int32, 'opencr/moving_servo_speed', + self._moving_servo_speed_cb, 10) - self._start_head_servo_audio_recording_sub = rospy.Subscriber('opencr/start_head_servo_audio_recording', Empty, - self._start_head_servo_audio_recording_cb, queue_size=10) - self._stop_head_servo_audio_recording_sub = rospy.Subscriber('opencr/stop_head_servo_audio_recording', Empty, - self._stop_head_servo_audio_recording_cb, queue_size=10) + self._start_head_servo_audio_recording_sub = self.create_subscription(Empty, 'opencr/start_head_servo_audio_recording', + self._start_head_servo_audio_recording_cb, 10) + self._stop_head_servo_audio_recording_sub = self.create_subscription(Empty, 'opencr/stop_head_servo_audio_recording', + self._stop_head_servo_audio_recording_cb, 10) - self._start_torso_servo_audio_recording_sub = rospy.Subscriber('opencr/start_torso_servo_audio_recording', Empty, - self._start_torso_servo_audio_recording_cb, queue_size=10) - self._stop_torso_servo_audio_recording_sub = rospy.Subscriber('opencr/stop_torso_servo_audio_recording', Empty, - self._stop_torso_servo_audio_recording_cb, queue_size=10) + self._start_torso_servo_audio_recording_sub = self.create_subscription(Empty, 'opencr/start_torso_servo_audio_recording', + self._start_torso_servo_audio_recording_cb, 10) + self._stop_torso_servo_audio_recording_sub = self.create_subscription(Empty, 'opencr/stop_torso_servo_audio_recording', + self._stop_torso_servo_audio_recording_cb, 10) - self._audio_sub = rospy.Subscriber('audio_in', AudioFrame, self._audio_cb, queue_size=100) + self._audio_sub = self.create_subscription(AudioFrame, 'audio_in', self._audio_cb, 100) - self._ego_noise_data_gathering_finished_sub = rospy.Subscriber('opencr/ego_noise_data_gathering_finished', Empty, - self._ego_noise_data_gathering_finished_cb, queue_size=10) + self._ego_noise_data_gathering_finished_sub = self.create_subscription(Empty, 'opencr/ego_noise_data_gathering_finished', + self._ego_noise_data_gathering_finished_cb, 10) def _write_noise_data_info(self): with open(os.path.join(self._noise_data_directory_path, 'info.txt'), 'w') as f: @@ -237,47 +238,39 @@ def _write_noise_data_info(self): f.write(f'{self._channel_count}\n') def _current_torso_orientation_cb(self, msg): - with self._lock: - self._torso_orientation_deg = math.degrees(msg.data) + self._torso_orientation_deg = math.degrees(msg.data) def _moving_servo_id_cb(self, msg): - with self._lock: - self._moving_servo_id = msg.data + self._moving_servo_id = msg.data def _moving_servo_speed_cb(self, msg): - with self._lock: - base = 5 - self._moving_servo_speed = base * round(msg.data / base) + base = 5 + self._moving_servo_speed = base * round(msg.data / base) def _start_head_servo_audio_recording_cb(self, msg): - with self._lock: - self._is_head_servo_audio_recording = True + self._is_head_servo_audio_recording = True def _stop_head_servo_audio_recording_cb(self, msg): - with self._lock: - self._is_head_servo_audio_recording = False + self._is_head_servo_audio_recording = False def _start_torso_servo_audio_recording_cb(self, msg): - with self._lock: - self._is_torso_servo_audio_recording = True + self._is_torso_servo_audio_recording = True def _stop_torso_servo_audio_recording_cb(self, msg): - with self._lock: - self._is_torso_servo_audio_recording = False + self._is_torso_servo_audio_recording = False def _audio_cb(self, msg): if msg.format != SUPPORTED_AUDIO_FORMAT or \ msg.channel_count != self._channel_count or \ msg.sampling_frequency != self._sampling_frequency: - rospy.logerr('Invalid audio frame (msg.format={}, msg.channel_count={}, msg.sampling_frequency={}})' + self.get_logger().error('Invalid audio frame (msg.format={}, msg.channel_count={}, msg.sampling_frequency={}})' .format(msg.format, msg.channel_count, msg.sampling_frequency)) return - with self._lock: - if self._is_head_servo_audio_recording: - self._append_to(self._get_head_servo_path(), msg.data) - if self._is_torso_servo_audio_recording: - self._append_to(self._get_torso_servo_path(), msg.data) + if self._is_head_servo_audio_recording: + self._append_to(self._get_head_servo_path(), msg.data) + if self._is_torso_servo_audio_recording: + self._append_to(self._get_torso_servo_path(), msg.data) def _get_head_servo_path(self): deg = round(self._torso_orientation_deg) % CIRCLE_DEGREES @@ -299,20 +292,25 @@ def _ego_noise_data_gathering_finished_cb(self, msg): self._audio_analyzer.analyse(self._audio_data_directory_path, self._noise_data_directory_path) def run(self): - rospy.sleep(STARTUP_DELAY_S) + time.sleep(STARTUP_DELAY_S) self._start_ego_noise_data_gathering_pub.publish(Empty()) - rospy.spin() + rclpy.spin(self) def main(): - rospy.init_node('data_gathering') - split_channel_node = DataGatheringNode() - split_channel_node.run() - + rclpy.init() + data_gathering = DataGatheringNode() -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + data_gathering.run() + except KeyboardInterrupt: pass + finally: + data_gathering.destroy_node() + + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/perceptions/ego_noise_reduction/scripts/test.py b/ros/perceptions/ego_noise_reduction/scripts/test.py old mode 100644 new mode 100755 index a591b01c..5ced22b1 --- a/ros/perceptions/ego_noise_reduction/scripts/test.py +++ b/ros/perceptions/ego_noise_reduction/scripts/test.py @@ -1,9 +1,13 @@ #!/usr/bin/env python3 +import threading import math +import time -import rospy -from hbba_lite.srv import SetOnOffFilterState +import rclpy +import rclpy.node + +from hbba_lite_srvs.srv import SetOnOffFilterState from t_top import MovementCommands @@ -11,16 +15,20 @@ PAUSE_DURATION_S = 5.0 -class EgoNoiseReductionTestNode: +class EgoNoiseReductionTestNode(rclpy.node.Node): def __init__(self): - self._movement_commands = MovementCommands() + super().__init__('ego_noise_reduction_test_node') + self._movement_commands = MovementCommands(self) def run(self): self._enable_on_off_filter('ego_noise_reduction/filter_state') self._enable_on_off_filter('pose/filter_state') - while not rospy.is_shutdown(): - rospy.sleep(PAUSE_DURATION_S) + executer_thread = threading.Thread(target=lambda: rclpy.spin(self)) + executer_thread.start() + + while rclpy.ok(): + time.sleep(PAUSE_DURATION_S) self._movement_commands.move_torso(math.pi / 2, should_wait=True) self._movement_commands.move_torso(-math.pi / 2, should_wait=True) @@ -28,20 +36,32 @@ def run(self): self._movement_commands.move_no(speed_rad_sec=0.5) self._movement_commands.move_maybe(speed_rad_sec=1.5) + executer_thread.join() + def _enable_on_off_filter(self, name): - rospy.wait_for_service(name) - filter_state = rospy.ServiceProxy(name, SetOnOffFilterState) - filter_state(is_filtering_all_messages=False) + client = self.create_client(SetOnOffFilterState, name) + client.wait_for_service() + request = SetOnOffFilterState.Request() + request.is_filtering_all_messages = False -def main(): - rospy.init_node('ego_noise_reduction_test_node') - capture_voice_node = EgoNoiseReductionTestNode() - capture_voice_node.run() + future = client.call_async(request) + rclpy.spin_until_future_complete(self, future) -if __name__ == '__main__': +def main(): + rclpy.init() + ego_noise_reduction_test_node = EgoNoiseReductionTestNode() + try: - main() - except rospy.ROSInterruptException: + ego_noise_reduction_test_node.run() + except KeyboardInterrupt: pass + finally: + ego_noise_reduction_test_node.destroy_node() + + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/perceptions/ego_noise_reduction/src/ego_noise_reduction/LogMmseNoiseRemover.cpp b/ros/perceptions/ego_noise_reduction/src/ego_noise_reduction/LogMmseNoiseRemover.cpp index d64bfa2b..4375a2d0 100644 --- a/ros/perceptions/ego_noise_reduction/src/ego_noise_reduction/LogMmseNoiseRemover.cpp +++ b/ros/perceptions/ego_noise_reduction/src/ego_noise_reduction/LogMmseNoiseRemover.cpp @@ -8,7 +8,6 @@ #include using namespace introlab; -using namespace boost::math; using namespace std; @@ -75,7 +74,7 @@ void LogMmseNoiseRemover::updateSpectrum( m_A = m_aPrioriSnr / (1.f + m_aPrioriSnr); m_H = m_A % m_aPosterioriSnr; - m_H.transform([](float v) { return -0.5f * expint(-v); }); + m_H.transform([](float v) { return -0.5f * boost::math::expint(-v); }); m_H = m_A % arma::exp(m_H); output = m_H % input; diff --git a/ros/perceptions/ego_noise_reduction/src/ego_noise_reduction_node.cpp b/ros/perceptions/ego_noise_reduction/src/ego_noise_reduction_node.cpp index 87daa9d3..c01e7a68 100644 --- a/ros/perceptions/ego_noise_reduction/src/ego_noise_reduction_node.cpp +++ b/ros/perceptions/ego_noise_reduction/src/ego_noise_reduction_node.cpp @@ -6,16 +6,17 @@ #include #include -#include -#include -#include -#include +#include -#include +#include +#include +#include + +#include #include -#include +#include #include @@ -26,10 +27,11 @@ using namespace introlab; using namespace std; -constexpr uint32_t AudioQueueSize = 100; constexpr uint32_t StatusQueueSize = 1; constexpr size_t HeadServoCount = 6; +constexpr const char* NODE_NAME = "ego_noise_reduction_node"; + struct EgoNoiseReductionNodeConfiguration { string typeString; @@ -55,7 +57,9 @@ struct EgoNoiseReductionNodeConfiguration float logMmseMaxAPosterioriSnr; float logMmseMinAPrioriSnr; - EgoNoiseReductionNodeConfiguration() + size_t audioQueueSize; + + EgoNoiseReductionNodeConfiguration(rclcpp::Node* node) : format(PcmAudioFrameFormat::Signed8), channelCount(0), samplingFrequency(0), @@ -71,45 +75,76 @@ struct EgoNoiseReductionNodeConfiguration logMmseMaxAPosterioriSnr(0.f), logMmseMinAPrioriSnr(0.f) { + typeString = node->declare_parameter("type", "log_mmse"); + type = StftNoiseRemover::parseType(typeString); + + formatString = node->declare_parameter("format", "signed_32"); + format = parseFormat(formatString); + + channelCount = node->declare_parameter("channel_count", 16); + samplingFrequency = node->declare_parameter("sampling_frequency", 16000); + frameSampleCount = node->declare_parameter("frame_sample_count", 1024); + nFft = node->declare_parameter("n_fft", 1024); + + noiseDirectory = node->declare_parameter("noise_directory", ""); + + noiseEstimatorEpsilon = node->declare_parameter("noise_estimator_epsilon", 4.f); + noiseEstimatorAlpha = node->declare_parameter("noise_estimator_alpha", 0.9f); + noiseEstimatorDelta = node->declare_parameter("noise_estimator_delta", 0.9f); + + spectralSubstractionAlpha0 = node->declare_parameter("spectral_subtraction_alpha0", 5.f); + spectralSubstractionGamma = node->declare_parameter("spectral_subtraction_gamma", 0.1f); + spectralSubstractionBeta = node->declare_parameter("spectral_subtraction_beta", 0.01f); + + logMmseAlpha = node->declare_parameter("log_mmse_alpha", 0.98f); + logMmseMaxAPosterioriSnr = node->declare_parameter("log_mmse_max_a_posteriori_snr", 40.f); + logMmseMinAPrioriSnr = node->declare_parameter("log_mmse_min_a_priori_snr", 0.003f); + + audioQueueSize = node->declare_parameter("audio_queue_size", 1); } }; -class EgoNoiseReductionNode +class EgoNoiseReductionNode : public rclcpp::Node { - ros::NodeHandle& m_nodeHandle; EgoNoiseReductionNodeConfiguration m_configuration; OnOffHbbaFilterState m_filterState; - ros::Publisher m_audioPub; - ros::Subscriber m_audioSub; + rclcpp::Publisher::SharedPtr m_audioPub; + rclcpp::Subscription::SharedPtr m_audioSub; - ros::Subscriber m_motorStatusSub; + rclcpp::Subscription::SharedPtr m_motorStatusSub; PcmAudioFrame m_inputPcmAudioFrame; size_t m_inputPcmAudioFrameIndex; PackedAudioFrame m_inputAudioFrame; PcmAudioFrame m_outputPcmAudioFrame; - std::queue m_timestampQueue; - audio_utils::AudioFrame m_audioFrameMsg; + std::queue m_timestampQueue; + audio_utils_msgs::msg::AudioFrame m_audioFrameMsg; shared_ptr m_noiseEstimator; unique_ptr m_noiseRemover; public: - EgoNoiseReductionNode(ros::NodeHandle& nodeHandle, EgoNoiseReductionNodeConfiguration configuration) - : m_nodeHandle(nodeHandle), - m_configuration(move(configuration)), - m_filterState(m_nodeHandle, "ego_noise_reduction/filter_state"), + EgoNoiseReductionNode() + : rclcpp::Node(NODE_NAME), + m_configuration(this), + m_filterState(*this, "ego_noise_reduction/filter_state"), m_inputPcmAudioFrame(m_configuration.format, m_configuration.channelCount, m_configuration.nFft), m_inputPcmAudioFrameIndex(0), m_inputAudioFrame(m_configuration.channelCount, m_configuration.nFft), m_outputPcmAudioFrame(m_configuration.format, m_configuration.channelCount, m_configuration.nFft) { - m_audioPub = m_nodeHandle.advertise("audio_out", AudioQueueSize); - m_audioSub = m_nodeHandle.subscribe("audio_in", AudioQueueSize, &EgoNoiseReductionNode::audioCallback, this); + m_audioPub = create_publisher("audio_out", m_configuration.audioQueueSize); + m_audioSub = create_subscription( + "audio_in", + m_configuration.audioQueueSize, + [this](const audio_utils_msgs::msg::AudioFrame::SharedPtr msg) { audioCallback(msg); }); - m_motorStatusSub = m_nodeHandle.subscribe("daemon/motor_status", StatusQueueSize, &EgoNoiseReductionNode::motorStatusCallback, this); + m_motorStatusSub = create_subscription( + "daemon/motor_status", + StatusQueueSize, + [this](const daemon_ros_client::msg::MotorStatus::SharedPtr msg) { motorStatusCallback(msg); }); m_audioFrameMsg.format = m_configuration.formatString; m_audioFrameMsg.channel_count = m_configuration.channelCount; @@ -118,7 +153,7 @@ class EgoNoiseReductionNode m_audioFrameMsg.data.resize( size(m_configuration.format, m_configuration.channelCount, m_configuration.frameSampleCount)); - m_noiseEstimator = make_shared( + m_noiseEstimator = std::make_shared( m_configuration.channelCount, m_configuration.nFft, m_configuration.samplingFrequency, @@ -129,17 +164,18 @@ class EgoNoiseReductionNode m_noiseRemover = createNoiseRemover(); } - void run() { ros::spin(); } + void run() { rclcpp::spin(shared_from_this()); } private: - void audioCallback(const audio_utils::AudioFrame::ConstPtr& msg) + void audioCallback(const audio_utils_msgs::msg::AudioFrame::SharedPtr msg) { if (msg->format != m_configuration.formatString || msg->channel_count != m_configuration.channelCount || msg->sampling_frequency != m_configuration.samplingFrequency || msg->frame_sample_count != m_configuration.frameSampleCount || msg->data.size() != size(m_configuration.format, msg->channel_count, msg->frame_sample_count)) { - ROS_ERROR( + RCLCPP_ERROR( + get_logger(), "Not supported audio frame (msg->format=%s, msg->channel_count=%d," "sampling_frequency=%d, frame_sample_count=%d, data_size=%lu)", msg->format.c_str(), @@ -178,13 +214,13 @@ class EgoNoiseReductionNode { m_audioFrameMsg.header.stamp = m_timestampQueue.front(); memcpy(m_audioFrameMsg.data.data(), frame.data() + i, m_audioFrameMsg.data.size()); - m_audioPub.publish(m_audioFrameMsg); + m_audioPub->publish(m_audioFrameMsg); m_timestampQueue.pop(); } } - void motorStatusCallback(const daemon_ros_client::MotorStatus::ConstPtr& msg) + void motorStatusCallback(const daemon_ros_client::msg::MotorStatus::SharedPtr msg) { if (m_filterState.isFilteringAllMessages()) { @@ -206,7 +242,7 @@ class EgoNoiseReductionNode switch (m_configuration.type) { case StftNoiseRemover::Type::SpectralSubtraction: - return make_unique( + return std::make_unique( m_configuration.channelCount, m_configuration.nFft, m_noiseEstimator, @@ -214,7 +250,7 @@ class EgoNoiseReductionNode m_configuration.spectralSubstractionGamma, m_configuration.spectralSubstractionBeta); case StftNoiseRemover::Type::LogMmse: - return make_unique( + return std::make_unique( m_configuration.channelCount, m_configuration.nFft, m_noiseEstimator, @@ -229,76 +265,20 @@ class EgoNoiseReductionNode int main(int argc, char** argv) { - ros::init(argc, argv, "ego_noise_reduction_node"); - - ros::NodeHandle nodeHandle; - ros::NodeHandle privateNodeHandle("~"); - - EgoNoiseReductionNodeConfiguration configuration; + rclcpp::init(argc, argv); try { - if (!privateNodeHandle.getParam("type", configuration.typeString)) - { - ROS_ERROR("The parameter type must be spectral_subtraction or log_mmse."); - return -1; - } - configuration.type = StftNoiseRemover::parseType(configuration.typeString); - - if (!privateNodeHandle.getParam("format", configuration.formatString)) - { - ROS_ERROR("The parameter format is required."); - return -1; - } - configuration.format = parseFormat(configuration.formatString); - - if (!privateNodeHandle.getParam("channel_count", configuration.channelCount)) - { - ROS_ERROR("The parameter channel_count is required."); - return -1; - } - if (!privateNodeHandle.getParam("sampling_frequency", configuration.samplingFrequency)) - { - ROS_ERROR("The parameter sampling_frequency is required."); - return -1; - } - if (!privateNodeHandle.getParam("frame_sample_count", configuration.frameSampleCount)) - { - ROS_ERROR("The parameter frame_sample_count is required."); - return -1; - } - if (!privateNodeHandle.getParam("n_fft", configuration.nFft) || - (configuration.nFft % configuration.frameSampleCount) != 0) - { - ROS_ERROR("The parameter n_fft is required. It must be a multiple of frame_sample_count."); - return -1; - } - if (!privateNodeHandle.getParam("noise_directory", configuration.noiseDirectory)) - { - ROS_ERROR("The parameter noise_directory is required."); - return -1; - } - - configuration.noiseEstimatorEpsilon = privateNodeHandle.param("noise_estimator_epsilon", 4.f); - configuration.noiseEstimatorAlpha = privateNodeHandle.param("noise_estimator_alpha", 0.9f); - configuration.noiseEstimatorDelta = privateNodeHandle.param("noise_estimator_delta", 0.9f); - - configuration.spectralSubstractionAlpha0 = privateNodeHandle.param("spectral_subtraction_alpha0", 5.f); - configuration.spectralSubstractionGamma = privateNodeHandle.param("spectral_subtraction_gamma", 0.1f); - configuration.spectralSubstractionBeta = privateNodeHandle.param("spectral_subtraction_beta", 0.01f); - - configuration.logMmseAlpha = privateNodeHandle.param("log_mmse_alpha", 0.98f); - configuration.logMmseMaxAPosterioriSnr = privateNodeHandle.param("log_mmse_max_a_posteriori_snr", 40.f); - configuration.logMmseMinAPrioriSnr = privateNodeHandle.param("log_mmse_min_a_priori_snr", 0.003f); - - EgoNoiseReductionNode node(nodeHandle, configuration); - node.run(); + auto node = std::make_shared(); + node->run(); } catch (const std::exception& e) { - ROS_ERROR_STREAM(e.what()); + RCLCPP_ERROR_STREAM(rclcpp::get_logger(NODE_NAME), e.what()); return -1; } + rclcpp::shutdown(); + return 0; } diff --git a/ros/perceptions/odas_ros b/ros/perceptions/odas_ros index 5e186cfc..012b765b 160000 --- a/ros/perceptions/odas_ros +++ b/ros/perceptions/odas_ros @@ -1 +1 @@ -Subproject commit 5e186cfc3da873e5a29789b1ab243c1eed72c9ff +Subproject commit 012b765b5350442c327cd5c5d9cd6dd64ac3985f diff --git a/ros/perceptions/perception_msgs/CMakeLists.txt b/ros/perceptions/perception_msgs/CMakeLists.txt new file mode 100644 index 00000000..0a048bdd --- /dev/null +++ b/ros/perceptions/perception_msgs/CMakeLists.txt @@ -0,0 +1,42 @@ +cmake_minimum_required(VERSION 3.5) +project(perception_msgs) + + +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(std_msgs REQUIRED) +find_package(sensor_msgs REQUIRED) +find_package(geometry_msgs REQUIRED) +find_package(visualization_msgs REQUIRED) +find_package(audio_utils_msgs REQUIRED) +find_package(rosidl_default_generators REQUIRED) + +# Generate messages +rosidl_generate_interfaces(${PROJECT_NAME} + "msg/AudioAnalysis.msg" + "msg/PersonName.msg" + "msg/PersonNames.msg" + "msg/PoseClassification.msg" + "msg/PoseClassifications.msg" + "msg/SemanticSegmentation.msg" + "msg/Transcript.msg" + "msg/VideoAnalysis.msg" + "msg/VideoAnalysisObject.msg" + DEPENDENCIES std_msgs sensor_msgs geometry_msgs visualization_msgs audio_utils_msgs +) + +ament_package() diff --git a/ros/perceptions/audio_analyzer/msg/AudioAnalysis.msg b/ros/perceptions/perception_msgs/msg/AudioAnalysis.msg similarity index 83% rename from ros/perceptions/audio_analyzer/msg/AudioAnalysis.msg rename to ros/perceptions/perception_msgs/msg/AudioAnalysis.msg index 4ae74f15..9f1d8849 100644 --- a/ros/perceptions/audio_analyzer/msg/AudioAnalysis.msg +++ b/ros/perceptions/perception_msgs/msg/AudioAnalysis.msg @@ -1,7 +1,7 @@ std_msgs/Header header int64 tracking_id -audio_utils/AudioFrame audio_frame +audio_utils_msgs/AudioFrame audio_frame string[] audio_classes float32[] audio_descriptor diff --git a/ros/perceptions/person_identification/msg/PersonName.msg b/ros/perceptions/perception_msgs/msg/PersonName.msg similarity index 100% rename from ros/perceptions/person_identification/msg/PersonName.msg rename to ros/perceptions/perception_msgs/msg/PersonName.msg diff --git a/ros/perceptions/perception_msgs/msg/PersonNames.msg b/ros/perceptions/perception_msgs/msg/PersonNames.msg new file mode 100644 index 00000000..e5bd80b9 --- /dev/null +++ b/ros/perceptions/perception_msgs/msg/PersonNames.msg @@ -0,0 +1 @@ +perception_msgs/PersonName[] names diff --git a/ros/perceptions/pose_classifier/msg/PoseClassification.msg b/ros/perceptions/perception_msgs/msg/PoseClassification.msg similarity index 74% rename from ros/perceptions/pose_classifier/msg/PoseClassification.msg rename to ros/perceptions/perception_msgs/msg/PoseClassification.msg index bb363684..3945dd73 100644 --- a/ros/perceptions/pose_classifier/msg/PoseClassification.msg +++ b/ros/perceptions/perception_msgs/msg/PoseClassification.msg @@ -5,4 +5,4 @@ string head_horizontal_class string left_arm_class string right_arm_class -video_analyzer/VideoAnalysisObject object +perception_msgs/VideoAnalysisObject object diff --git a/ros/perceptions/perception_msgs/msg/PoseClassifications.msg b/ros/perceptions/perception_msgs/msg/PoseClassifications.msg new file mode 100644 index 00000000..a29a6760 --- /dev/null +++ b/ros/perceptions/perception_msgs/msg/PoseClassifications.msg @@ -0,0 +1,2 @@ +std_msgs/Header header +perception_msgs/PoseClassification[] poses diff --git a/ros/perceptions/video_analyzer/msg/SemanticSegmentation.msg b/ros/perceptions/perception_msgs/msg/SemanticSegmentation.msg similarity index 100% rename from ros/perceptions/video_analyzer/msg/SemanticSegmentation.msg rename to ros/perceptions/perception_msgs/msg/SemanticSegmentation.msg diff --git a/ros/perceptions/speech_to_text/msg/Transcript.msg b/ros/perceptions/perception_msgs/msg/Transcript.msg similarity index 100% rename from ros/perceptions/speech_to_text/msg/Transcript.msg rename to ros/perceptions/perception_msgs/msg/Transcript.msg diff --git a/ros/perceptions/perception_msgs/msg/VideoAnalysis.msg b/ros/perceptions/perception_msgs/msg/VideoAnalysis.msg new file mode 100644 index 00000000..f9e46baf --- /dev/null +++ b/ros/perceptions/perception_msgs/msg/VideoAnalysis.msg @@ -0,0 +1,6 @@ +std_msgs/Header header + +bool contains_3d_positions +perception_msgs/VideoAnalysisObject[] objects +perception_msgs/SemanticSegmentation[] semantic_segmentation +float32 processing_time_s diff --git a/ros/perceptions/video_analyzer/msg/VideoAnalysisObject.msg b/ros/perceptions/perception_msgs/msg/VideoAnalysisObject.msg similarity index 100% rename from ros/perceptions/video_analyzer/msg/VideoAnalysisObject.msg rename to ros/perceptions/perception_msgs/msg/VideoAnalysisObject.msg diff --git a/ros/perceptions/perception_msgs/package.xml b/ros/perceptions/perception_msgs/package.xml new file mode 100644 index 00000000..75e81abb --- /dev/null +++ b/ros/perceptions/perception_msgs/package.xml @@ -0,0 +1,28 @@ + + + + perception_msgs + 0.0.0 + The perception_msgs package + Marc-Antoine Maheux + GPL-3.0 license + + ament_cmake + rosidl_default_generators + + std_msgs + sensor_msgs + geometry_msgs + visualization_msgs + audio_utils_msgs + + rosidl_default_runtime + rosidl_interface_packages + + ament_lint_auto + ament_lint_common + + + ament_cmake + + diff --git a/ros/perceptions/person_identification/.gitignore b/ros/perceptions/person_identification/.gitignore deleted file mode 100644 index e2349e92..00000000 --- a/ros/perceptions/person_identification/.gitignore +++ /dev/null @@ -1 +0,0 @@ -people.json diff --git a/ros/perceptions/person_identification/CMakeLists.txt b/ros/perceptions/person_identification/CMakeLists.txt index c33f217a..c3c82021 100644 --- a/ros/perceptions/person_identification/CMakeLists.txt +++ b/ros/perceptions/person_identification/CMakeLists.txt @@ -1,211 +1,45 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(person_identification) -## Compile as C++11, supported in ROS Kinetic and newer -# add_compile_options(-std=c++11) -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - audio_analyzer - hbba_lite - rospy - tf - video_analyzer - std_msgs - geometry_msgs +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclpy REQUIRED) +find_package(audio_analyzer REQUIRED) +find_package(hbba_lite REQUIRED) +find_package(tf2 REQUIRED) +find_package(tf2_ros REQUIRED) +find_package(video_analyzer REQUIRED) +find_package(std_msgs REQUIRED) +find_package(geometry_msgs REQUIRED) +find_package(perception_msgs REQUIRED) + +# Python Librairies +ament_python_install_package(${PROJECT_NAME}) + +# Python Nodes +install(PROGRAMS + scripts/capture_face_node.py + scripts/capture_voice_node.py + scripts/person_identification_node.py + DESTINATION lib/${PROJECT_NAME} ) -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) +# Launch files +install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}) - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -add_message_files( - FILES - PersonName.msg - PersonNames.msg -) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -generate_messages( - DEPENDENCIES - std_msgs - geometry_msgs -) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( -# INCLUDE_DIRS include -# LIBRARIES person_identification -# CATKIN_DEPENDS audio_analyzer hbba_lite rospy std_msgs tf video_analyzer -# DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( -# include - ${catkin_INCLUDE_DIRS} -) - -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/person_identification.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -# add_executable(${PROJECT_NAME}_node src/person_identification_node.cpp) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -# target_link_libraries(${PROJECT_NAME}_node -# ${catkin_LIBRARIES} -# ) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -# catkin_install_python(PROGRAMS -# scripts/my_python_script -# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_person_identification.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() - -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/perceptions/person_identification/README.md b/ros/perceptions/person_identification/README.md index ef508f3a..0cee277f 100644 --- a/ros/perceptions/person_identification/README.md +++ b/ros/perceptions/person_identification/README.md @@ -7,16 +7,16 @@ This node adds to `people.json` an averaged face descriptor for the person in fr Use the following command to launch the nodes. ```bash -roslaunch person_identification capture_face.launch name:= neural_network_inference_type:= +ros2 launch person_identification capture_face.launch.xml name:= neural_network_inference_type:= ``` #### Parameters - `name` (string): The person name. - - `mean_size` (int): How many descriptor to average. - - `face_sharpness_score_threshold` (double): The threshold to consider the face sharp enough. + - `mean_size` (int): How many descriptor to average. The default value is 10. + - `face_sharpness_score_threshold` (double): The threshold to consider the face sharp enough. The default value is 0.5. #### Subscribed Topics - - `video_analysis` ([video_analyzer/VideoAnalysis](../video_analyzer/msg/VideoAnalysis.msg)): The video analysis containing the detected objects. + - `video_analysis` ([perception_msgs/VideoAnalysis](../perception_msgs/msg/VideoAnalysis.msg)): The video analysis containing the detected objects. ### `capture_voice_node.py` @@ -24,34 +24,34 @@ This node adds to `people.json` an averaged voice descriptor for the person talk Use the following command to launch the nodes. ```bash -roslaunch person_identification capture_voice.launch name:= neural_network_inference_type:= +ros2 launch person_identification capture_voice.launch.xml name:= neural_network_inference_type:= ``` #### Parameters - `name` (string): The person name. - - `mean_size` (int): How many descriptor to average. + - `mean_size` (int): How many descriptor to average. The default value is 10. #### Subscribed Topics - - `audio_analysis` ([audio_analyzer/AudioAnalysis](../audio_analyzer/msg/AudioAnalysis.msg)): The audio analysis containing the audio classes, general audio embedding, voice embedding and the sound direction. + - `audio_analysis` ([perception_msgs/AudioAnalysis](../perception_msgs/msg/AudioAnalysis.msg)): The audio analysis containing the audio classes, general audio embedding, voice embedding and the sound direction. ### `person_identification_node.py` This node performs person identification. The people must be already added to `people.json` with the previous nodes. #### Parameters - - `face_sharpness_score_threshold` (double): The threshold to consider the face sharp enough. - - `face_descriptor_threshold` (double): The maximum distance between two face descriptors to be considered the same person. - - `voice_descriptor_threshold` (double): The maximum distance between two voice descriptors to be considered the same person. - - `face_voice_descriptor_threshold` (double): The maximum distance between two merged descriptors to be considered the same person. - - `nose_confidence_threshold` (double): The confidence threshold for the nose keypoint. - - `direction_frame_id` (string): The audio analysis frame id. - - `direction_angle_threshold_rad` (double): The maximum angle between the face and voice directions to be considered the same person. - - `ignore_direction_z` (bool): Indicates if the angle between between the face and voice directions ignores the z-axis. - - `search_frequency` (double): The frequency at which the search occurs. + - `face_sharpness_score_threshold` (double): The threshold to consider the face sharp enough. The default value is 0.5. + - `face_descriptor_threshold` (double): The maximum distance between two face descriptors to be considered the same person. The default value is 0.7. + - `voice_descriptor_threshold` (double): The maximum distance between two voice descriptors to be considered the same person. The default value is 1.266. + - `face_voice_descriptor_threshold` (double): The maximum distance between two merged descriptors to be considered the same person. The default value is 1.5092. + - `nose_confidence_threshold` (double): The confidence threshold for the nose keypoint. The default value is 0.4. + - `direction_frame_id` (string): The audio analysis frame id. The default value is odas. + - `direction_angle_threshold_rad` (double): The maximum angle between the face and voice directions to be considered the same person. The default value is 0.15. + - `ignore_direction_z` (bool): Indicates if the angle between between the face and voice directions ignores the z-axis. The default value is true. + - `search_frequency` (double): The frequency at which the search occurs. The default value is 2. #### Subscribed Topics - - `video_analysis` ([video_analyzer/VideoAnalysis](../video_analyzer/msg/VideoAnalysis.msg)): The video analysis containing the detected objects. - - `audio_analysis` ([audio_analyzer/AudioAnalysis](../audio_analyzer/msg/AudioAnalysis.msg)): The audio analysis containing the audio classes, general audio embedding, voice embedding and the sound direction. + - `video_analysis` ([perception_msgs/VideoAnalysis](../perception_msgs/msg/VideoAnalysis.msg)): The video analysis containing the detected objects. + - `audio_analysis` ([perception_msgs/AudioAnalysis](../perception_msgs/msg/AudioAnalysis.msg)): The audio analysis containing the audio classes, general audio embedding, voice embedding and the sound direction. #### Published Topics - - `person_names` ([person_identification/PersonNames](msg/PersonNames.msg)): The person names. + - `person_names` ([perception_msgs/PersonNames](../perception_msgs/msg/PersonNames.msg)): The person names. diff --git a/ros/perceptions/person_identification/launch/capture_face.launch b/ros/perceptions/person_identification/launch/capture_face.launch.xml similarity index 57% rename from ros/perceptions/person_identification/launch/capture_face.launch rename to ros/perceptions/person_identification/launch/capture_face.launch.xml index 200c3ceb..9671d5ce 100644 --- a/ros/perceptions/person_identification/launch/capture_face.launch +++ b/ros/perceptions/person_identification/launch/capture_face.launch.xml @@ -2,40 +2,29 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - + - + + @@ -48,9 +37,9 @@ - - - + + + diff --git a/ros/perceptions/person_identification/launch/capture_voice.launch b/ros/perceptions/person_identification/launch/capture_voice.launch.xml similarity index 65% rename from ros/perceptions/person_identification/launch/capture_voice.launch rename to ros/perceptions/person_identification/launch/capture_voice.launch.xml index 49cbd4ec..d18a58b1 100644 --- a/ros/perceptions/person_identification/launch/capture_voice.launch +++ b/ros/perceptions/person_identification/launch/capture_voice.launch.xml @@ -2,7 +2,7 @@ - + @@ -12,16 +12,13 @@ + - - - [front-left, front-right, rear-left, rear-right, front-center, lfe, side-left, side-right, aux0, aux1, aux2, aux3, aux4, aux5, aux6, aux7] - - - + + @@ -30,9 +27,9 @@ - - - + + + @@ -41,8 +38,8 @@ - - + + diff --git a/ros/perceptions/person_identification/msg/PersonNames.msg b/ros/perceptions/person_identification/msg/PersonNames.msg deleted file mode 100644 index 13152d27..00000000 --- a/ros/perceptions/person_identification/msg/PersonNames.msg +++ /dev/null @@ -1 +0,0 @@ -person_identification/PersonName[] names diff --git a/ros/perceptions/person_identification/package.xml b/ros/perceptions/person_identification/package.xml index 2909d57f..770c0d0a 100644 --- a/ros/perceptions/person_identification/package.xml +++ b/ros/perceptions/person_identification/package.xml @@ -1,81 +1,31 @@ - + + person_identification 0.0.0 The person_identification package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rclpy + audio_analyzer + hbba_lite + tf2 + tf2_ros + video_analyzer + std_msgs + geometry_msgs + perception_msgs - - - - TODO + rosidl_default_runtime + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - message_generation - audio_analyzer - hbba_lite - rospy - std_msgs - geometry_msgs - tf - video_analyzer - audio_analyzer - hbba_lite - rospy - std_msgs - geometry_msgs - tf - video_analyzer - audio_analyzer - hbba_lite - rospy - std_msgs - geometry_msgs - tf - video_analyzer - - - - - + ament_cmake diff --git a/ros/perceptions/person_identification/src/person_identification/__init__.py b/ros/perceptions/person_identification/person_identification/__init__.py similarity index 92% rename from ros/perceptions/person_identification/src/person_identification/__init__.py rename to ros/perceptions/person_identification/person_identification/__init__.py index ae089341..6eac9244 100644 --- a/ros/perceptions/person_identification/src/person_identification/__init__.py +++ b/ros/perceptions/person_identification/person_identification/__init__.py @@ -3,10 +3,8 @@ import numpy as np -import rospkg -PACKAGE_PATH = rospkg.RosPack().get_path('person_identification') -PEOPLE_FILE_PATH = os.path.join(PACKAGE_PATH, 'people.json') +PEOPLE_FILE_PATH = os.path.join(os.environ['HOME'], '.ros', 't-top', 'person_identification', 'people.json') def verify_people(people): @@ -64,6 +62,7 @@ def load_people(): def save_people(people): verify_people(people) + os.makedirs(os.path.dirname(PEOPLE_FILE_PATH), exist_ok=True) with open(PEOPLE_FILE_PATH, 'w') as people_file: people = json.dump(people, people_file) diff --git a/ros/perceptions/person_identification/scripts/capture_face_node.py b/ros/perceptions/person_identification/scripts/capture_face_node.py index 0bc52bfb..2beb031f 100755 --- a/ros/perceptions/person_identification/scripts/capture_face_node.py +++ b/ros/perceptions/person_identification/scripts/capture_face_node.py @@ -1,80 +1,84 @@ #!/usr/bin/env python3 -import threading - import numpy as np -import rospy -from hbba_lite.srv import SetThrottlingFilterState -from video_analyzer.msg import VideoAnalysis - -import person_identification +import rclpy +import rclpy.node +from hbba_lite_srvs.srv import SetThrottlingFilterState +from perception_msgs.msg import VideoAnalysis -INACTIVE_SLEEP_DURATION = 0.1 +import person_identification -class CaptureFaceNode: +class CaptureFaceNode(rclpy.node.Node): def __init__(self): - self._name = rospy.get_param('~name') - self._mean_size = rospy.get_param('~mean_size') - self._face_sharpness_score_threshold = rospy.get_param('~face_sharpness_score_threshold') + super().__init__('capture_face_node') + + self._name = self.declare_parameter('name', '').get_parameter_value().string_value + self._mean_size = self.declare_parameter('mean_size', 10).get_parameter_value().integer_value + self._face_sharpness_score_threshold = self.declare_parameter('face_sharpness_score_threshold', 0.5).get_parameter_value().double_value - self._descriptors_lock = threading.Lock() self._descriptors = [] - self._video_analysis_sub = rospy.Subscriber('video_analysis', VideoAnalysis, self._video_analysis_cb, queue_size=1) + self._video_analysis_sub = self.create_subscription(VideoAnalysis, 'video_analysis', self._video_analysis_cb, 1) def _video_analysis_cb(self, msg): face_object = None for object in msg.objects: if len(object.face_descriptor) > 0 and face_object is not None: - rospy.logwarn('Only one face must be present in the image.') + self.get_logger().warn('Only one face must be present in the image.') elif len(object.face_descriptor) > 0: face_object = object if face_object is not None and face_object.face_sharpness_score >= self._face_sharpness_score_threshold: - with self._descriptors_lock: - self._descriptors.append(face_object.face_descriptor) + self._descriptors.append(face_object.face_descriptor) def run(self): self.enable_video_analyzer() - while not rospy.is_shutdown(): - with self._descriptors_lock: - size = len(self._descriptors) - - if size == self._mean_size: - self._video_analysis_sub.unregister() + while rclpy.ok(): + if len(self._descriptors) == self._mean_size: + self.destroy_subscription(self._video_analysis_sub) self._save_new_descriptor() return else: - rospy.sleep(INACTIVE_SLEEP_DURATION) + rclpy.spin_once(self) def enable_video_analyzer(self): VIDEO_ANALYZER_FILTER_STATE_SERVICE = 'video_analyzer/image_raw/filter_state' - rospy.wait_for_service(VIDEO_ANALYZER_FILTER_STATE_SERVICE) - filter_state = rospy.ServiceProxy(VIDEO_ANALYZER_FILTER_STATE_SERVICE, SetThrottlingFilterState) - filter_state(is_filtering_all_messages=False, rate=1) + client = self.create_client(SetThrottlingFilterState, VIDEO_ANALYZER_FILTER_STATE_SERVICE) + client.wait_for_service() + + request = SetThrottlingFilterState.Request() + request.is_filtering_all_messages = False + request.rate = 1 + + future = client.call_async(request) + rclpy.spin_until_future_complete(self, future) def _save_new_descriptor(self): - with self._descriptors_lock: - descriptor = np.array(self._descriptors).mean(axis=0).tolist() - people = person_identification.load_people() - person_identification.add_person(people, self._name, {'face': descriptor}) - person_identification.save_people(people) + descriptor = np.array(self._descriptors).mean(axis=0).tolist() + people = person_identification.load_people() + person_identification.add_person(people, self._name, {'face': descriptor}) + person_identification.save_people(people) - rospy.loginfo('*********************** FINISHED ***********************') + self.get_logger().info('*********************** FINISHED ***********************') def main(): - rospy.init_node('capture_face_node') + rclpy.init() capture_face_node = CaptureFaceNode() - capture_face_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + capture_face_node.run() + except KeyboardInterrupt: pass + finally: + capture_face_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/perceptions/person_identification/scripts/capture_voice_node.py b/ros/perceptions/person_identification/scripts/capture_voice_node.py index 81a2dfdc..9ab5c1bd 100755 --- a/ros/perceptions/person_identification/scripts/capture_voice_node.py +++ b/ros/perceptions/person_identification/scripts/capture_voice_node.py @@ -1,75 +1,80 @@ #!/usr/bin/env python3 -import threading - import numpy as np -import rospy -from hbba_lite.srv import SetOnOffFilterState -from audio_analyzer.msg import AudioAnalysis - -import person_identification +import rclpy +import rclpy.node +from hbba_lite_srvs.srv import SetOnOffFilterState +from perception_msgs.msg import AudioAnalysis -INACTIVE_SLEEP_DURATION = 0.1 +import person_identification -class CaptureVoiceNode: +class CaptureVoiceNode(rclpy.node.Node): def __init__(self): - self._name = rospy.get_param('~name') - self._mean_size = rospy.get_param('~mean_size') + super().__init__('capture_voice_node') + + self._name = self.declare_parameter('name', '').get_parameter_value().string_value + self._mean_size = self.declare_parameter('mean_size', 10).get_parameter_value().integer_value - self._descriptors_lock = threading.Lock() self._descriptors = [] - self.audio_analysis = rospy.Subscriber('audio_analysis', AudioAnalysis, self._audio_analysis_cb, queue_size=1) + self._audio_analysis_sub = self.create_subscription(AudioAnalysis, 'audio_analysis', self._audio_analysis_cb, 1) def _audio_analysis_cb(self, msg): if len(msg.voice_descriptor) > 0: - with self._descriptors_lock: - self._descriptors.append(msg.voice_descriptor) - print('voice') + self._descriptors.append(msg.voice_descriptor) + self.get_logger().info('voice') else: - print('no voice') + self.get_logger().info('no voice') def run(self): self.enable_audio_analyzer() - while not rospy.is_shutdown(): - with self._descriptors_lock: - size = len(self._descriptors) + while rclpy.ok(): + size = len(self._descriptors) if size == self._mean_size: - self.audio_analysis.unregister() + self.destroy_subscription(self._audio_analysis_sub) self._save_new_descriptor() return else: - rospy.sleep(INACTIVE_SLEEP_DURATION) + rclpy.spin_once(self) def enable_audio_analyzer(self): AUDIO_ANALYZER_FILTER_STATE_SERVICE = 'audio_analyzer/filter_state' - rospy.wait_for_service(AUDIO_ANALYZER_FILTER_STATE_SERVICE) - filter_state = rospy.ServiceProxy(AUDIO_ANALYZER_FILTER_STATE_SERVICE, SetOnOffFilterState) - filter_state(is_filtering_all_messages=False) + client = self.create_client(SetOnOffFilterState, AUDIO_ANALYZER_FILTER_STATE_SERVICE) + client.wait_for_service() + + request = SetOnOffFilterState.Request() + request.is_filtering_all_messages = False + + future = client.call_async(request) + rclpy.spin_until_future_complete(self, future) def _save_new_descriptor(self): - with self._descriptors_lock: - descriptor = np.array(self._descriptors).mean(axis=0).tolist() - people = person_identification.load_people() - person_identification.add_person(people, self._name, {'voice': descriptor}) - person_identification.save_people(people) + descriptor = np.array(self._descriptors).mean(axis=0).tolist() + people = person_identification.load_people() + person_identification.add_person(people, self._name, {'voice': descriptor}) + person_identification.save_people(people) - rospy.loginfo('*********************** FINISHED ***********************') + self.get_logger().info('*********************** FINISHED ***********************') def main(): - rospy.init_node('capture_voice_node') + rclpy.init() capture_voice_node = CaptureVoiceNode() - capture_voice_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + capture_voice_node.run() + except KeyboardInterrupt: pass + finally: + capture_voice_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/perceptions/person_identification/scripts/person_identification_node.py b/ros/perceptions/person_identification/scripts/person_identification_node.py index 3e308a3b..5b346df2 100755 --- a/ros/perceptions/person_identification/scripts/person_identification_node.py +++ b/ros/perceptions/person_identification/scripts/person_identification_node.py @@ -1,15 +1,18 @@ #!/usr/bin/env python3 -import threading - import numpy as np -import rospy -import tf +import rclpy +import rclpy.node +import rclpy.time + +from tf2_ros import TransformException +from tf2_ros.buffer import Buffer +from tf2_ros.transform_listener import TransformListener +import tf2_geometry_msgs + from geometry_msgs.msg import PointStamped, Point, Vector3 -from video_analyzer.msg import VideoAnalysis -from audio_analyzer.msg import AudioAnalysis -from person_identification.msg import PersonNames, PersonName +from perception_msgs.msg import VideoAnalysis, AudioAnalysis, PersonNames, PersonName import person_identification @@ -39,31 +42,36 @@ def __init__(self, descriptor, direction): self.direction = direction -class PersonIdentificationNode: +class PersonIdentificationNode(rclpy.node.Node): def __init__(self): - self._face_sharpness_score_threshold = rospy.get_param('~face_sharpness_score_threshold') - self._face_descriptor_threshold = rospy.get_param('~face_descriptor_threshold') - self._voice_descriptor_threshold = rospy.get_param('~voice_descriptor_threshold') - self._face_voice_descriptor_threshold = rospy.get_param('~face_voice_descriptor_threshold') - self._nose_confidence_threshold = rospy.get_param('~nose_confidence_threshold') - self._direction_frame_id = rospy.get_param('~direction_frame_id') - self._direction_angle_threshold_rad = rospy.get_param('~direction_angle_threshold_rad') - self._ignore_direction_z = rospy.Rate(rospy.get_param('~ignore_direction_z')) - self._rate = rospy.Rate(rospy.get_param('~search_frequency')) + super().__init__('person_identification_node') + + self._face_sharpness_score_threshold = self.declare_parameter('face_sharpness_score_threshold', 0.5).get_parameter_value().double_value + self._face_descriptor_threshold = self.declare_parameter('face_descriptor_threshold', 0.7).get_parameter_value().double_value + self._voice_descriptor_threshold = self.declare_parameter('voice_descriptor_threshold', 1.266).get_parameter_value().double_value + self._face_voice_descriptor_threshold = self.declare_parameter('face_voice_descriptor_threshold', 1.5092).get_parameter_value().double_value + self._nose_confidence_threshold = self.declare_parameter('nose_confidence_threshold', 0.4).get_parameter_value().double_value + self._direction_frame_id = self.declare_parameter('direction_frame_id', 'odas').get_parameter_value().string_value + self._direction_angle_threshold_rad = self.declare_parameter('direction_angle_threshold_rad', 0.15).get_parameter_value().double_value + self._ignore_direction_z = self.declare_parameter('ignore_direction_z', True).get_parameter_value().bool_value + self._search_frequency = self.declare_parameter('search_frequency', 2.0).get_parameter_value().double_value self._face_descriptors_by_name = {} self._voice_descriptors_by_name = {} self._face_voice_descriptors_by_name = {} self._load_descriptors() - self._descriptors_lock = threading.Lock() self._face_descriptor_data = [] self._voice_descriptor_data = None - self._person_name_pub = rospy.Publisher('person_names', PersonNames, queue_size=5) + self._person_name_pub = self.create_publisher(PersonNames, 'person_names', 5) + + self._tf_buffer = Buffer() + self._tf_listener = TransformListener(self._tf_buffer, self) - self._tf_listener = tf.TransformListener() - self._video_analysis_sub = rospy.Subscriber('video_analysis', VideoAnalysis, self._video_analysis_cb, queue_size=1) - self.audio_analysis = rospy.Subscriber('audio_analysis', AudioAnalysis, self._audio_analysis_cb, queue_size=1) + self._video_analysis_sub = self.create_subscription(VideoAnalysis, 'video_analysis', self._video_analysis_cb, 10) + self._audio_analysis = self.create_subscription(AudioAnalysis, 'audio_analysis', self._audio_analysis_cb, 10) + + self._timer = self.create_timer(1 / self._search_frequency, self._timer_callback) def _load_descriptors(self): people = person_identification.load_people() @@ -77,17 +85,17 @@ def _load_descriptors(self): def _video_analysis_cb(self, msg): if not msg.contains_3d_positions: - rospy.logerr('The video analysis must contain 3d positions.') + self.get_logger().error('The video analysis must contain 3d positions.') return - with self._descriptors_lock: - for object in msg.objects: - if len(object.face_descriptor) == 0 or len(object.person_pose_2d) == 0 or len(object.person_pose_3d) == 0 \ - or len(object.person_pose_confidence) == 0 \ - or object.person_pose_confidence[PERSON_POSE_NOSE_INDEX] < self._nose_confidence_threshold \ - or object.face_sharpness_score < self._face_sharpness_score_threshold: - continue + for object in msg.objects: + if len(object.face_descriptor) == 0 or len(object.person_pose_2d) == 0 or len(object.person_pose_3d) == 0 \ + or len(object.person_pose_confidence) == 0 \ + or object.person_pose_confidence[PERSON_POSE_NOSE_INDEX] < self._nose_confidence_threshold \ + or object.face_sharpness_score < self._face_sharpness_score_threshold: + continue + try: position_2d = object.person_pose_2d[PERSON_POSE_NOSE_INDEX] position_3d, direction = self._get_face_position_3d_and_direction(object.person_pose_3d[PERSON_POSE_NOSE_INDEX], msg.header) if np.isfinite(direction).all(): @@ -95,6 +103,8 @@ def _video_analysis_cb(self, msg): position_2d, position_3d, direction)) + except TransformException as ex: + self.get_logger().warn(f'Could not transform: {ex}') def _get_face_position_3d_and_direction(self, point, header): temp_in_point = PointStamped() @@ -103,7 +113,8 @@ def _get_face_position_3d_and_direction(self, point, header): temp_in_point.point.y = point.y temp_in_point.point.z = point.z - odas_point = self._tf_listener.transformPoint(self._direction_frame_id, temp_in_point) + transform = self._tf_buffer.lookup_transform(self._direction_frame_id, header.frame_id, rclpy.time.Time.from_msg(header.stamp)) + odas_point = tf2_geometry_msgs.do_transform_point(temp_in_point, transform) position = np.array([odas_point.point.x, odas_point.point.y, odas_point.point.z]) direction = position.copy() @@ -115,7 +126,7 @@ def _get_face_position_3d_and_direction(self, point, header): def _audio_analysis_cb(self, msg): if msg.header.frame_id != self._direction_frame_id: - rospy.logerr(f'Invalid frame id ({msg.header.frame_id} != {self._direction_frame_id})') + self.get_logger().error(f'Invalid frame id ({msg.header.frame_id} != {self._direction_frame_id})') return if len(msg.voice_descriptor) == 0: @@ -127,22 +138,21 @@ def _audio_analysis_cb(self, msg): voice_direction /= np.linalg.norm(voice_direction) if np.isfinite(voice_direction).all(): - with self._descriptors_lock: - self._voice_descriptor_data = VoiceDescriptorData(np.array(msg.voice_descriptor), voice_direction) + self._voice_descriptor_data = VoiceDescriptorData(np.array(msg.voice_descriptor), voice_direction) - def run(self): - while not rospy.is_shutdown(): - with self._descriptors_lock: - names = [] - names.extend(self._find_face_voice_descriptor_name()) - names.extend(self._find_voice_descriptor_name()) - names.extend(self._find_face_descriptor_names()) + def _timer_callback(self): + names = [] + names.extend(self._find_face_voice_descriptor_name()) + names.extend(self._find_voice_descriptor_name()) + names.extend(self._find_face_descriptor_names()) - self._face_descriptor_data.clear() - self._voice_descriptor_data = None + self._face_descriptor_data.clear() + self._voice_descriptor_data = None - self._publish_names(names) - self._rate.sleep() + self._publish_names(names) + + def run(self): + rclpy.spin(self) def _find_face_voice_descriptor_name(self): if self._voice_descriptor_data is None or len(self._face_descriptor_data) == 0 or \ @@ -238,13 +248,18 @@ def _filter_names(self, names): def main(): - rospy.init_node('person_identification_node') + rclpy.init() person_identification_node = PersonIdentificationNode() - person_identification_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + person_identification_node.run() + except KeyboardInterrupt: pass + finally: + person_identification_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/perceptions/person_identification/setup.py b/ros/perceptions/person_identification/setup.py deleted file mode 100644 index 5dc6816b..00000000 --- a/ros/perceptions/person_identification/setup.py +++ /dev/null @@ -1,12 +0,0 @@ -## ! DO NOT MANUALLY INVOKE THIS setup.py, USE CATKIN INSTEAD - -from distutils.core import setup -from catkin_pkg.python_setup import generate_distutils_setup - -# fetch values from package.xml -setup_args = generate_distutils_setup( - packages=['person_identification'], - package_dir={'': 'src'}, -) - -setup(**setup_args) diff --git a/ros/perceptions/pose_classifier/CMakeLists.txt b/ros/perceptions/pose_classifier/CMakeLists.txt index 7631ed39..55309846 100644 --- a/ros/perceptions/pose_classifier/CMakeLists.txt +++ b/ros/perceptions/pose_classifier/CMakeLists.txt @@ -1,215 +1,35 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(pose_classifier) -## Compile as C++11, supported in ROS Kinetic and newer -# add_compile_options(-std=c++11) - -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - rospy - message_generation - video_analyzer - std_msgs - geometry_msgs - sensor_msgs - visualization_msgs - hbba_lite -) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -add_message_files( - FILES - PoseClassification.msg - PoseClassifications.msg -) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -generate_messages( - DEPENDENCIES - std_msgs # Or other packages containing msgs - video_analyzer - geometry_msgs - sensor_msgs - visualization_msgs -) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( -# INCLUDE_DIRS include -# LIBRARIES pose_classifier -# CATKIN_DEPENDS rospy video_analyzer -# DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( -# include - ${catkin_INCLUDE_DIRS} -) - -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/pose_classifier.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -# add_executable(${PROJECT_NAME}_node src/pose_classifier_node.cpp) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -# target_link_libraries(${PROJECT_NAME}_node -# ${catkin_LIBRARIES} -# ) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -catkin_install_python(PROGRAMS +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclpy REQUIRED) +find_package(video_analyzer REQUIRED) +find_package(std_msgs REQUIRED) +find_package(geometry_msgs REQUIRED) +find_package(sensor_msgs REQUIRED) +find_package(visualization_msgs REQUIRED) +find_package(hbba_lite REQUIRED) +find_package(perception_msgs REQUIRED) + +# Python Nodes +install(PROGRAMS scripts/pose_classifier_node.py - DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} + DESTINATION lib/${PROJECT_NAME} ) -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_pose_classifier.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() - -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/perceptions/pose_classifier/README.md b/ros/perceptions/pose_classifier/README.md index d6e197d4..54bdc661 100644 --- a/ros/perceptions/pose_classifier/README.md +++ b/ros/perceptions/pose_classifier/README.md @@ -6,13 +6,13 @@ This folder contains the node to perform pose classification from the pose extra This node performs pose classification from the pose extracted by the [video_analyzer](../video_analyzer). #### Parameters - - `pose_confidence_threshold` (double): The pose confidence threshold to determine if a joint is present. + - `pose_confidence_threshold` (double): The pose confidence threshold to determine if a joint is present. The default value is 0.4. #### Subscribed Topics - - `video_analysis` ([video_analyzer/VideoAnalysis](../video_analyzer/msg/VideoAnalysis.msg)): The video analysis topic. + - `video_analysis` ([perception_msgs/VideoAnalysis](../perception_msgs/msg/VideoAnalysis.msg)): The video analysis topic. #### Published Topics -- `pose_classification` ([pose_classifier/PoseClassifications](msg/PoseClassifications.msg)): The pose classification topic. +- `pose_classification` ([perception_msgs/PoseClassifications](../perception_msgs/msg/PoseClassifications.msg)): The pose classification topic. ## Pose classes - **head_vertical_class** diff --git a/ros/perceptions/pose_classifier/msg/PoseClassifications.msg b/ros/perceptions/pose_classifier/msg/PoseClassifications.msg deleted file mode 100644 index ea30848b..00000000 --- a/ros/perceptions/pose_classifier/msg/PoseClassifications.msg +++ /dev/null @@ -1,2 +0,0 @@ -std_msgs/Header header -pose_classifier/PoseClassification[] poses diff --git a/ros/perceptions/pose_classifier/package.xml b/ros/perceptions/pose_classifier/package.xml index 8e8f0eb5..88232cd5 100644 --- a/ros/perceptions/pose_classifier/package.xml +++ b/ros/perceptions/pose_classifier/package.xml @@ -1,83 +1,30 @@ - + + pose_classifier 0.0.0 The pose_classifier package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rclpy + video_analyzer + std_msgs + geometry_msgs + sensor_msgs + visualization_msgs + hbba_lite + perception_msgs - - - - TODO + rosidl_default_runtime + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - rospy - message_generation - video_analyzer - std_msgs - geometry_msgs - sensor_msgs - visualization_msgs - hbba_lite - rospy - message_generation - video_analyzer - std_msgs - geometry_msgs - sensor_msgs - visualization_msgs - hbba_lite - rospy - message_generation - video_analyzer - std_msgs - geometry_msgs - sensor_msgs - visualization_msgs - hbba_lite - - - - - + ament_cmake diff --git a/ros/perceptions/pose_classifier/scripts/pose_classifier_node.py b/ros/perceptions/pose_classifier/scripts/pose_classifier_node.py index 8567f620..9e588891 100755 --- a/ros/perceptions/pose_classifier/scripts/pose_classifier_node.py +++ b/ros/perceptions/pose_classifier/scripts/pose_classifier_node.py @@ -2,10 +2,10 @@ import numpy as np -import rospy -from video_analyzer.msg import VideoAnalysis +import rclpy +import rclpy.node -from pose_classifier.msg import PoseClassification, PoseClassifications +from perception_msgs.msg import VideoAnalysis, PoseClassification, PoseClassifications NOSE_INDEX = 0 @@ -63,12 +63,14 @@ def vector_angle(v1, v2, eps=1e-9): return np.sign(c[2]) * abs_angle -class PoseClassifierNode: +class PoseClassifierNode(rclpy.node.Node): def __init__(self): - self._pose_confidence_threshold = rospy.get_param('~pose_confidence_threshold', 0.4) + super().__init__('pose_classifier_node') - self._pose_classification_pub = rospy.Publisher('pose_classification', PoseClassifications, queue_size=1) - self._video_analysis_sub = rospy.Subscriber('video_analysis', VideoAnalysis, self._video_analysis_cb, queue_size=1) + self._pose_confidence_threshold = self.declare_parameter('pose_confidence_threshold', 0.4).get_parameter_value().double_value + + self._pose_classification_pub = self.create_publisher(PoseClassifications, 'pose_classification', 1) + self._video_analysis_sub = self.create_subscription(VideoAnalysis, 'video_analysis', self._video_analysis_cb, 1) def _video_analysis_cb(self, video_analysis_msg): pose_classifications_msg = PoseClassifications() @@ -223,17 +225,22 @@ def _classify_arm_angles(self, shoulder_elbow_angle_rad, elbow_wrist_angle_rad): return '' def run(self): - rospy.spin() + rclpy.spin(self) def main(): - rospy.init_node('pose_classifier_node') + rclpy.init() pose_classifier_node = PoseClassifierNode() - pose_classifier_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + pose_classifier_node.run() + except KeyboardInterrupt: pass + finally: + pose_classifier_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/perceptions/robot_name_detector/CMakeLists.txt b/ros/perceptions/robot_name_detector/CMakeLists.txt index 13282105..232845d4 100644 --- a/ros/perceptions/robot_name_detector/CMakeLists.txt +++ b/ros/perceptions/robot_name_detector/CMakeLists.txt @@ -1,207 +1,35 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(robot_name_detector) -## Compile as C++11, supported in ROS Kinetic and newer -# add_compile_options(-std=c++11) - -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - audio_utils - rospy - hbba_lite - daemon_ros_client -) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -# add_message_files( -# FILES -# Message1.msg -# Message2.msg -# ) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -# generate_messages( -# DEPENDENCIES -# std_msgs # Or other packages containing msgs -# ) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( -# INCLUDE_DIRS include -# LIBRARIES robot_name_detector -# CATKIN_DEPENDS audio_utils rospy -# DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( -# include - ${catkin_INCLUDE_DIRS} -) - -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/robot_name_detector.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -# add_executable(${PROJECT_NAME}_node src/robot_name_detector_node.cpp) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -# target_link_libraries(${PROJECT_NAME}_node -# ${catkin_LIBRARIES} -# ) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -catkin_install_python(PROGRAMS +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclpy REQUIRED) +find_package(dnn_utils REQUIRED) +find_package(audio_utils_msgs REQUIRED) +find_package(hbba_lite REQUIRED) +find_package(daemon_ros_client REQUIRED) + +# Python Nodes +install(PROGRAMS scripts/robot_name_detector_node.py - DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} + DESTINATION lib/${PROJECT_NAME} ) -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_robot_name_detector.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() +# Launch files +install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}) -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/perceptions/robot_name_detector/README.md b/ros/perceptions/robot_name_detector/README.md index 0ffcdd2b..15ca1bfa 100644 --- a/ros/perceptions/robot_name_detector/README.md +++ b/ros/perceptions/robot_name_detector/README.md @@ -6,24 +6,26 @@ This folder contains the node to detect the robot name. This node measures the sound level and detects the robot name. #### Parameters - - `message_rate` (int): The frequency of `sound_rms` and `sound_presence` messages. - - `sound_rms_attack` (double): The attack value of the sound level filter (default: 0.05). - - `sound_rms_release` (double): The release value of the sound level filter (default: 0.99). - - `sound_rms_presence_threshold` (double): The threshold of the sound precense (default: 0.05). - - `inference_type` (string): Indicates where to run the neural network (cpu, torch_gpu or trt_gpu). - - `robot_name_model_probability_threshold` (double): The joint probability threshold. - - `robot_name_model_interval` (int): The interval between inferences in sample. - - `robot_name_model_analysis_delay` (int): The delay after the rising edge in sample. - - `robot_name_model_analysis_count` (int): The number of inference to perform. + - `led_status_duration_s` (double): The LED status duration en seconds. The default value is 1.0. + - `sound_presence_relative_threshold` (double): The relative threshold of the sound precense between the slow and fast filter. The default value is 1.05. + - `robot_name_model_probability_threshold` (double): The joint probability threshold. The default value is 0.05. + - `robot_name_model_interval` (int): The interval between inferences in sample. The default value is 800. + - `robot_name_model_analysis_delay` (int): The delay after the rising edge in sample. The default value is 10400. + - `robot_name_model_analysis_count` (int): The number of inference to perform. The default value is 3. + - `fast_sound_rms_attack` (double): The fast attack value of the sound level filter. The default value is 0.05. + - `fast_sound_rms_release` (double): The fast release value of the sound level filter The default value is 0.9. + - `slow_sound_rms_attack` (double): The slow attack value of the sound level filter. The default value is 0.975. + - `slow_sound_rms_release` (double): The slow release value of the sound level filter The default value is 0.975. + - `inference_type` (string): Indicates where to run the neural network (cpu, torch_gpu or trt_gpu). The default value is cpu. #### Subscribed Topics - - `audio_in` ([audio_utils/AudioFrame](https://github.com/introlab/audio_utils/blob/main/msg/AudioFrame.msg)): The sound topic processed, which must be signed_16, at 16000 Hz and 1 channel. + - `audio_in` ([audio_utils_msgs/AudioFrame](https://github.com/introlab/audio_utils/blob/ros2/audio_utils_msgs/msg/AudioFrame.msg)): The sound topic processed, which must be signed_16, at 16000 Hz and 1 channel. #### Published Topics - - `sound_rms` ([std_msgs/Float32](http://docs.ros.org/en/noetic/api/std_msgs/html/msg/Float32.html)): The sound level. - - `sound_presence` ([std_msgs/Bool](http://docs.ros.org/en/noetic/api/std_msgs/html/msg/Bool.html)): Indicates if sound is presence. - - `robot_name_detected` ([std_msgs/Empty](http://docs.ros.org/en/noetic/api/std_msgs/html/msg/Empty.html)): Indicates that the robot name is detected. + - `sound_rms` ([std_msgs/Float32](https://docs.ros.org/en/humble/p/std_msgs/interfaces/msg/Float32.html)): The sound level. + - `sound_presence` ([std_msgs/Bool](https://docs.ros.org/en/humble/p/std_msgs/interfaces/msg/Bool.html)): Indicates if sound is presence. + - `robot_name_detected` ([std_msgs/Empty](https://docs.ros.org/en/humble/p/std_msgs/interfaces/msg/Empty.html)): Indicates that the robot name is detected. - `robot_name_detector/set_led_colors` ([daemon_ros_client/LedColors](../../daemon_ros_client/msg/LedColors.msg)): The LED colors for the status. #### Services - - `audio_in/filter_state` ([hbba_lite/SetOnOffFilterState](../../hbba_lite/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the processing. + - `audio_in/filter_state` ([hbba_lite_srvs/SetOnOffFilterState](../../utils/hbba_lite/hbba_lite_srvs/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the processing. diff --git a/ros/t_top/launch/tests/test_robot_name_detector.launch b/ros/perceptions/robot_name_detector/launch/test_robot_name_detector.launch.xml similarity index 81% rename from ros/t_top/launch/tests/test_robot_name_detector.launch rename to ros/perceptions/robot_name_detector/launch/test_robot_name_detector.launch.xml index 32170cf1..d050080a 100644 --- a/ros/t_top/launch/tests/test_robot_name_detector.launch +++ b/ros/perceptions/robot_name_detector/launch/test_robot_name_detector.launch.xml @@ -1,20 +1,19 @@ - + - + - - + @@ -27,7 +26,7 @@ - + diff --git a/ros/perceptions/robot_name_detector/package.xml b/ros/perceptions/robot_name_detector/package.xml index f705a379..7585a37b 100644 --- a/ros/perceptions/robot_name_detector/package.xml +++ b/ros/perceptions/robot_name_detector/package.xml @@ -1,75 +1,27 @@ - + + robot_name_detector 0.0.0 The robot_name_detector package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rclpy + dnn_utils + audio_utils_msgs + hbba_lite + daemon_ros_client - - - - TODO + rosidl_default_runtime + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - audio_utils - rospy - std_msgs - hbba_lite - daemon_ros_client - audio_utils - rospy - std_msgs - hbba_lite - daemon_ros_client - audio_utils - rospy - std_msgs - dnn_utils - hbba_lite - daemon_ros_client - - - - - + ament_cmake diff --git a/ros/perceptions/robot_name_detector/scripts/robot_name_detector_node.py b/ros/perceptions/robot_name_detector/scripts/robot_name_detector_node.py index 5b1d8dee..6180f83e 100755 --- a/ros/perceptions/robot_name_detector/scripts/robot_name_detector_node.py +++ b/ros/perceptions/robot_name_detector/scripts/robot_name_detector_node.py @@ -4,9 +4,11 @@ import torch -import rospy +import rclpy +import rclpy.node + from std_msgs.msg import Float32, Bool, Empty -from audio_utils.msg import AudioFrame +from audio_utils_msgs.msg import AudioFrame from daemon_ros_client.msg import LedColors from dnn_utils import TTopKeywordSpotter @@ -41,24 +43,27 @@ def reset(self): self._sound_rms = 0.0 -class RobotNameDetectorNode: +class RobotNameDetectorNode(rclpy.node.Node): def __init__(self): - self._led_status_duration_s = rospy.get_param('~led_status_duration_s', 1.0) + super().__init__('robot_name_detector_node') + + self._led_status_duration_s = self.declare_parameter('led_status_duration_s', 1.0).get_parameter_value().double_value - self._sound_presence_relative_threshold = rospy.get_param('~sound_presence_relative_threshold', 1.05) + self._sound_presence_relative_threshold = self.declare_parameter('sound_presence_relative_threshold', 1.05).get_parameter_value().double_value - self._robot_name_model_probability_threshold = rospy.get_param('~robot_name_model_probability_threshold') - self._robot_name_model_interval = rospy.get_param('~robot_name_model_interval') - self._robot_name_model_analysis_delay = rospy.get_param('~robot_name_model_analysis_delay') - self._robot_name_model_analysis_count = rospy.get_param('~robot_name_model_analysis_count') + self._robot_name_model_probability_threshold = self.declare_parameter('robot_name_model_probability_threshold', 0.05).get_parameter_value().double_value + self._robot_name_model_interval = self.declare_parameter('robot_name_model_interval', 800).get_parameter_value().integer_value + self._robot_name_model_analysis_delay = self.declare_parameter('robot_name_model_analysis_delay', 10400).get_parameter_value().integer_value + self._robot_name_model_analysis_count = self.declare_parameter('robot_name_model_analysis_count', 3).get_parameter_value().integer_value - self._fast_sound_rms_filter = SoundRmsFilter(rospy.get_param('~fast_sound_rms_attack', 0.05), - rospy.get_param('~fast_sound_rms_release', 0.99)) - self._slow_sound_rms_filter = SoundRmsFilter(rospy.get_param('~slow_sound_rms_attack', 0.9), - rospy.get_param('~slow_sound_rms_release', 0.9), + self._fast_sound_rms_filter = SoundRmsFilter(self.declare_parameter('fast_sound_rms_attack', 0.05).get_parameter_value().double_value, + self.declare_parameter('fast_sound_rms_release', 0.99).get_parameter_value().double_value) + self._slow_sound_rms_filter = SoundRmsFilter(self.declare_parameter('slow_sound_rms_attack', 0.975).get_parameter_value().double_value, + self.declare_parameter('slow_sound_rms_release', 0.975).get_parameter_value().double_value, initial_sound_rms=0.1) - self._robot_name_model = TTopKeywordSpotter(inference_type=rospy.get_param('~inference_type', None)) + self._inference_type = self.declare_parameter('inference_type', 'cpu').get_parameter_value().string_value + self._robot_name_model = TTopKeywordSpotter(inference_type=self._inference_type) self._robot_name_model_output_index = self._robot_name_model.get_class_names().index('T-Top') self._robot_name_model_buffer = torch.zeros(self._robot_name_model.get_supported_duration(), dtype=torch.float32) @@ -73,17 +78,18 @@ def __init__(self): # Warm up, to avoid inference delays self._robot_name_model(self._robot_name_model_buffer) - self._fast_sound_rms_pub = rospy.Publisher('fast_sound_rms', Float32, queue_size=10) - self._slow_sound_rms_pub = rospy.Publisher('slow_sound_rms', Float32, queue_size=10) - self._sound_presence_pub = rospy.Publisher('sound_presence', Bool, queue_size=10) - self._robot_name_detected_pub = rospy.Publisher('robot_name_detected', Empty, queue_size=10) - self._led_colors_pub = hbba_lite.OnOffHbbaPublisher('robot_name_detector/set_led_colors', LedColors, queue_size=1, + self._fast_sound_rms_pub = self.create_publisher(Float32, 'fast_sound_rms', 10) + self._slow_sound_rms_pub = self.create_publisher(Float32, 'slow_sound_rms', 10) + self._sound_presence_pub = self.create_publisher(Bool, 'sound_presence', 10) + self._robot_name_detected_pub = self.create_publisher(Empty, 'robot_name_detected', 10) + + self._led_colors_pub = hbba_lite.OnOffHbbaPublisher(self, LedColors, 'robot_name_detector/set_led_colors', 1, state_service_name='led_status/filter_state') self._led_colors_pub.on_filter_state_changing(self._led_colors_hbba_filter_state_cb) - self._hbba_filter_state = hbba_lite.OnOffHbbaFilterState('audio_in/filter_state') + self._hbba_filter_state = hbba_lite.OnOffHbbaFilterState(self, 'audio_in/filter_state') self._hbba_filter_state.on_changed(self._robot_name_detector_hbba_state_changed_cb) - self._audio_sub = rospy.Subscriber('audio_in', AudioFrame, self._audio_cb, queue_size=100) + self._audio_sub = self.create_subscription(AudioFrame, 'audio_in', self._audio_cb, 100) def _led_colors_hbba_filter_state_cb(self, publish_forced, previous_is_filtering_all_messages, new_is_filtering_all_messages): @@ -97,15 +103,15 @@ def _audio_cb(self, msg): if msg.format != SUPPORTED_AUDIO_FORMAT or \ msg.channel_count != SUPPORTED_CHANNEL_COUNT or \ msg.sampling_frequency != self._robot_name_model.get_supported_sampling_frequency(): - rospy.logerr('Invalid audio frame (msg.format={}, msg.channel_count={}, msg.sampling_frequency={}})' - .format(msg.format, msg.channel_count, msg.sampling_frequency)) + self.get_logger().error( + f'Invalid audio frame (msg.format={msg.format}, msg.channel_count={msg.channel_count}, msg.sampling_frequency={msg.sampling_frequency})') return audio_frame = np.frombuffer(msg.data, dtype=np.int16).astype(np.float32) / -np.iinfo(np.int16).min frame_rms = np.sqrt(np.mean(audio_frame**2)) fast_sound_rms = self._fast_sound_rms_filter.update(frame_rms) slow_sound_rms = self._slow_sound_rms_filter.update(frame_rms) - presence = fast_sound_rms > slow_sound_rms * self._sound_presence_relative_threshold + presence = fast_sound_rms > (slow_sound_rms * self._sound_presence_relative_threshold) self._publish_sound_rms_messages(fast_sound_rms, slow_sound_rms, presence) @@ -124,7 +130,7 @@ def _publish_sound_rms_messages(self, fast_sound_rms, slow_sound_rms, presence): self._slow_sound_rms_pub.publish(sound_rms_msg) sound_presence_msg = Bool() - sound_presence_msg.data = presence + sound_presence_msg.data = bool(presence) self._sound_presence_pub.publish(sound_presence_msg) def _detect_robot_name(self, audio_frame, presence): @@ -159,7 +165,7 @@ def _publish_robot_name_detected_if_needed(self): else: self._detection_status = False - self._detection_time_s = rospy.get_time() + self._detection_time_s = self._now_s() def _detect_robot_name_if_needed(self): if self._robot_name_model_interval_count >= self._robot_name_model_interval: @@ -169,7 +175,7 @@ def _detect_robot_name_if_needed(self): self._robot_name_model_probabilities.append(probabilities[self._robot_name_model_output_index].item()) def _publish_led_status(self, fast_sound_rms, slow_sound_rms, eps=1e-6): - if rospy.get_time() - self._detection_time_s < self._led_status_duration_s and self._detection_status is not None: + if self._now_s() - self._detection_time_s < self._led_status_duration_s and self._detection_status is not None: if self._detection_status: self._publish_led_colors(0, 255, 0) else: @@ -192,17 +198,25 @@ def _publish_led_colors(self, red, green, blue): self._led_colors_pub.publish(msg) def run(self): - rospy.spin() + rclpy.spin(self) + + def _now_s(self): + return self.get_clock().now().nanoseconds / 1e9 def main(): - rospy.init_node('robot_name_detector_node') + rclpy.init() robot_name_detector_node = RobotNameDetectorNode() - robot_name_detector_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + robot_name_detector_node.run() + except KeyboardInterrupt: pass + finally: + robot_name_detector_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/perceptions/speech_to_text/CMakeLists.txt b/ros/perceptions/speech_to_text/CMakeLists.txt index 5cb0732d..7d46ec38 100644 --- a/ros/perceptions/speech_to_text/CMakeLists.txt +++ b/ros/perceptions/speech_to_text/CMakeLists.txt @@ -1,208 +1,35 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(speech_to_text) -## Compile as C++11, supported in ROS Kinetic and newer -# add_compile_options(-std=c++11) - -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - audio_utils - rospy - std_msgs - message_generation - hbba_lite -) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -add_message_files( - FILES - Transcript.msg -) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -generate_messages( - DEPENDENCIES - std_msgs -) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( -# INCLUDE_DIRS include -# LIBRARIES speech_to_text - CATKIN_DEPENDS audio_utils rospy std_msgs message_runtime -# DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( -# include - ${catkin_INCLUDE_DIRS} -) - -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/speech_to_text.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -# add_executable(${PROJECT_NAME}_node src/speech_to_text_node.cpp) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -# target_link_libraries(${PROJECT_NAME}_node -# ${catkin_LIBRARIES} -# ) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -catkin_install_python(PROGRAMS +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclpy REQUIRED) +find_package(audio_utils_msgs REQUIRED) +find_package(hbba_lite REQUIRED) +find_package(perception_msgs REQUIRED) + +# Python Nodes +install(PROGRAMS scripts/google_speech_to_text_node.py scripts/whisper_speech_to_text_node.py - DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} + DESTINATION lib/${PROJECT_NAME} ) -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_speech_to_text.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() +# Launch files +install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}) -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/perceptions/speech_to_text/README.md b/ros/perceptions/speech_to_text/README.md index e3a3d093..9394b9eb 100644 --- a/ros/perceptions/speech_to_text/README.md +++ b/ros/perceptions/speech_to_text/README.md @@ -6,39 +6,39 @@ This folder contains the nodes performing speech to text. The node performs speech to text. It uses Google Cloud Speech-to-Text. #### Parameters - - `sampling_frequency` (int): The input sampling frequency. - - `frame_sample_count` (int): The number of samples in each frame. - - `request_frame_count` (int): The number of frame in each request. - - `language` (string): The language (en or fr). + - `sampling_frequency` (int): The input sampling frequency. The default value is 16000. + - `frame_sample_count` (int): The number of samples in each frame. The default value is 92. + - `request_frame_count` (int): The number of frame in each request. The default value is 20. + - `language` (string): The language (en or fr). The default value is en. #### Subscribed Topics - - `audio_in` ([audio_utils/AudioFrame](https://github.com/introlab/audio_utils/blob/main/msg/AudioFrame.msg)): The sound topic processed. + - `audio_in` ([audio_utils_msgs/AudioFrame](https://github.com/introlab/audio_utils/blob/ros2/audio_utils_msgs/msg/AudioFrame.msg)): The sound topic processed. #### Published Topics - - `transcript` ([speech_to_text/Transcript](msg/Transcript.msg)): The text said. + - `transcript` ([perception_msgs/Transcript](../perception_msgs/msg/Transcript.msg)): The text said. #### Services - - `audio_in/filter_state` ([hbba_lite/SetOnOffFilterState](../../hbba_lite/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the processing. + - `audio_in/filter_state` ([hbba_lite_srvs/SetOnOffFilterState](../../utils/hbba_lite/hbba_lite_srvs/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the processing. ### `whisper_speech_to_text_node.py` The node performs speech to text. It uses [Faster Whisper](https://github.com/guillaumekln/faster-whisper). #### Parameters - - `language` (string): The language (en or fr). - - `model_size` (string): The [Whisper model size](https://github.com/openai/whisper#available-models-and-languages) + - `language` (string): The language (en or fr). The default value is en. + - `model_size` (string): The [Whisper model size](https://github.com/openai/whisper#available-models-and-languages). The default value is base.en. (tiny, tiny.en, base, base.en, small, small.en, medium, medium.en, large or large.en). - - `device` (string): The device that executes the model (cpu or cuda) - - `compute_type` (string): The compute type (int8, float16 or float32). - - `prebuffering_frame_count` (int): Number of frames to be accumulated before processing (default=4) - - `minimum_voice_sequence_size` (int): Minimum number of voice samples to be processed (default=8000) + - `device` (string): The device that executes the model (cpu or cuda). The default value is cpu. + - `compute_type` (string): The compute type (int8, float16 or float32). The default value is float32. + - `prebuffering_frame_count` (int): Number of frames to be accumulated before processing. The default value is 4. + - `minimum_voice_sequence_size` (int): Minimum number of voice samples to be processed. The default value is 8000. #### Subscribed Topics - - `voice_activity` ([audio_utils/VoiceActivity](https://github.com/introlab/audio_utils/blob/main/msg/VoiceActivity.msg)): The output of the voice activity detector. - - `audio_in` ([audio_utils/AudioFrame](https://github.com/introlab/audio_utils/blob/main/msg/AudioFrame.msg)): The sound topic processed. + - `voice_activity` ([audio_utils_msgs/VoiceActivity](https://github.com/introlab/audio_utils/blob/ros2/audio_utils_msgs/msg/VoiceActivity.msg)): The output of the voice activity detector. + - `audio_in` ([audio_utils_msgs/AudioFrame](https://github.com/introlab/audio_utils/blob/ros2/audio_utils_msgs/msg/AudioFrame.msg)): The sound topic processed. #### Published Topics - - `transcript` ([speech_to_text/Transcript](msg/Transcript.msg)): The text said. + - `transcript` ([perception_msgs/Transcript](../perception_msgs/msg/Transcript.msg)): The text said. #### Services - - `audio_in/filter_state` ([hbba_lite/SetOnOffFilterState](../../hbba_lite/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the processing. + - `audio_in/filter_state` ([hbba_lite_srvs/SetOnOffFilterState](../../utils/hbba_lite/hbba_lite_srvs/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the processing. diff --git a/ros/t_top/launch/tests/test_google_speech_to_text.launch b/ros/perceptions/speech_to_text/launch/test_google_speech_to_text_node.launch.xml similarity index 52% rename from ros/t_top/launch/tests/test_google_speech_to_text.launch rename to ros/perceptions/speech_to_text/launch/test_google_speech_to_text_node.launch.xml index ab3fe32f..bdfb0800 100644 --- a/ros/t_top/launch/tests/test_google_speech_to_text.launch +++ b/ros/perceptions/speech_to_text/launch/test_google_speech_to_text_node.launch.xml @@ -1,30 +1,26 @@ - - - - - - - - - - - - - - + - + - + + + + + + + + + + diff --git a/ros/perceptions/speech_to_text/launch/test_whisper_speech_to_text_node.launch.xml b/ros/perceptions/speech_to_text/launch/test_whisper_speech_to_text_node.launch.xml new file mode 100644 index 00000000..ee3cb5fa --- /dev/null +++ b/ros/perceptions/speech_to_text/launch/test_whisper_speech_to_text_node.launch.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ros/perceptions/speech_to_text/package.xml b/ros/perceptions/speech_to_text/package.xml index 3449f1a8..d7b3ce90 100644 --- a/ros/perceptions/speech_to_text/package.xml +++ b/ros/perceptions/speech_to_text/package.xml @@ -1,73 +1,26 @@ - + + speech_to_text 0.0.0 The speech_to_text package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rclpy + audio_utils_msgs + hbba_lite + perception_msgs - - - - TODO + rosidl_default_runtime + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - audio_utils - rospy - std_msgs - message_generation - hbba_lite - audio_utils - rospy - std_msgs - hbba_lite - audio_utils - rospy - std_msgs - message_runtime - hbba_lite - - - - - + ament_cmake diff --git a/ros/perceptions/speech_to_text/scripts/google_speech_to_text_node.py b/ros/perceptions/speech_to_text/scripts/google_speech_to_text_node.py index b04282ee..5cbf9621 100755 --- a/ros/perceptions/speech_to_text/scripts/google_speech_to_text_node.py +++ b/ros/perceptions/speech_to_text/scripts/google_speech_to_text_node.py @@ -6,9 +6,11 @@ import datetime import numpy as np -import rospy -from speech_to_text.msg import Transcript -from audio_utils.msg import AudioFrame +import rclpy +import rclpy.node + +from perception_msgs.msg import Transcript +from audio_utils_msgs.msg import AudioFrame import hbba_lite from google.cloud import speech @@ -19,28 +21,29 @@ SUPPORTED_CHANNEL_COUNT = 1 -class GoogleSpeechToTextNode: +class GoogleSpeechToTextNode(rclpy.node.Node): def __init__(self): - self._sampling_frequency = rospy.get_param('~sampling_frequency', 16000) - self._frame_sample_count = rospy.get_param('~frame_sample_count', 92) - self._request_frame_count = rospy.get_param('~request_frame_count', 20) - self._language_code = self._convert_language_to_language_code(rospy.get_param('~language')) + super().__init__('google_speech_to_text_node') + + self._sampling_frequency = self.declare_parameter('sampling_frequency', 16000).get_parameter_value().integer_value + self._frame_sample_count = self.declare_parameter('frame_sample_count', 92).get_parameter_value().integer_value + self._request_frame_count = self.declare_parameter('request_frame_count', 20).get_parameter_value().integer_value + + language = self.declare_parameter('language', 'en').get_parameter_value().string_value + self._language_code = self._convert_language_to_language_code(language) self._sleeping_duration = (self._request_frame_count * self._frame_sample_count / self._sampling_frequency) self._is_enabled = False - self._buffer_lock = threading.Lock() self._buffer = self._create_request_frame_buffer() self._current_buffer_index = 0 self._request_frame_queue = queue.Queue() self._total_samples_count = 0 - rospy.on_shutdown(self._shutdown_cb) - - self._text_pub = rospy.Publisher('transcript', Transcript, queue_size=10) - self._audio_sub = hbba_lite.OnOffHbbaSubscriber('audio_in', AudioFrame, self._audio_cb, queue_size=10) + self._text_pub = self.create_publisher(Transcript, 'transcript', 10) + self._audio_sub = hbba_lite.OnOffHbbaSubscriber(self, AudioFrame, 'audio_in', self._audio_cb, 10) self._audio_sub.on_filter_state_changed(self._filter_state_changed_cb) self._speech_client = speech.SpeechClient() @@ -59,38 +62,42 @@ def _audio_cb(self, msg): msg.channel_count != SUPPORTED_CHANNEL_COUNT or \ msg.sampling_frequency != self._sampling_frequency or \ msg.frame_sample_count != self._frame_sample_count: - rospy.logerr('Invalid audio frame (msg.format={}, msg.channel_count={}, msg.sampling_frequency={}, msg.frame_sample_count={}})' - .format(msg.format, msg.channel_count, msg.sampling_frequency, msg.frame_sample_count)) + self.get_logger().error( + f'Invalid audio frame (msg.format={msg.format}, msg.channel_count={msg.channel_count}' + + f', msg.sampling_frequency={msg.sampling_frequency}, msg.frame_sample_count={msg.frame_sample_count})') return - with self._buffer_lock: - audio_frame = np.frombuffer(msg.data, dtype=np.int16) - self._buffer[self._current_buffer_index:self._current_buffer_index + - self._frame_sample_count] = audio_frame + audio_frame = np.frombuffer(msg.data, dtype=np.int16) + self._buffer[self._current_buffer_index:self._current_buffer_index + + self._frame_sample_count] = audio_frame - self._current_buffer_index += self._frame_sample_count + self._current_buffer_index += self._frame_sample_count - if self._current_buffer_index >= self._buffer.shape[0]: - self._current_buffer_index = 0 - self._request_frame_queue.put(self._buffer.copy()) + if self._current_buffer_index >= self._buffer.shape[0]: + self._current_buffer_index = 0 + self._request_frame_queue.put(self._buffer.copy()) def _filter_state_changed_cb(self, previous_is_filtering_all_messages, new_is_filtering_all_messages): - with self._buffer_lock: - if previous_is_filtering_all_messages and not new_is_filtering_all_messages: - self._current_buffer_index = 0 - while not self._request_frame_queue.empty(): - self._request_frame_queue.get_nowait() - self._is_enabled = True - elif not previous_is_filtering_all_messages and new_is_filtering_all_messages: - self._is_enabled = False - self._request_frame_queue.put(None) - - def _shutdown_cb(self): - self._filter_state_changed_cb( - self._audio_sub.is_filtering_all_messages, True) + if previous_is_filtering_all_messages and not new_is_filtering_all_messages: + self._current_buffer_index = 0 + while not self._request_frame_queue.empty(): + self._request_frame_queue.get_nowait() + self._is_enabled = True + elif not previous_is_filtering_all_messages and new_is_filtering_all_messages: + self._is_enabled = False + self._request_frame_queue.put(None) def run(self): - while not rospy.is_shutdown(): + speech_to_text_thread = threading.Thread(target=self._speech_to_text_thread_run) + speech_to_text_thread.start() + + rclpy.spin(self) + + self._filter_state_changed_cb(self._audio_sub.is_filtering_all_messages, True) + speech_to_text_thread.join() + + def _speech_to_text_thread_run(self): + while rclpy.ok(): if not self._is_enabled: time.sleep(self._sleeping_duration) continue @@ -131,29 +138,34 @@ def _request_frame_generator(self): self._total_samples_count = 0 while self._is_enabled: audio_content = self._request_frame_queue.get() - self._total_samples_count += audio_content.shape[0] if audio_content is None: break - + + self._total_samples_count += audio_content.shape[0] yield speech.StreamingRecognizeRequest(audio_content=audio_content.tobytes()) def main(): - rospy.init_node('google_speech_to_text_node') + rclpy.init() + google_speech_to_text_node = GoogleSpeechToTextNode() - while not rospy.is_shutdown(): - try: - google_speech_to_text_node.run() - except (core_exceptions.InvalidArgument, - core_exceptions.Unknown, - core_exceptions.DeadlineExceeded, - core_exceptions.OutOfRange) as e: - rospy.logerr(f'google_speech_to_text_node has failed ({e})') + try: + while rclpy.ok(): + try: + google_speech_to_text_node.run() + except (core_exceptions.InvalidArgument, + core_exceptions.Unknown, + core_exceptions.DeadlineExceeded, + core_exceptions.OutOfRange) as e: + google_speech_to_text_node.get_logger().error(f'google_speech_to_text_node has failed ({e})') + except KeyboardInterrupt: + pass + finally: + google_speech_to_text_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() if __name__ == '__main__': - try: - main() - except rospy.ROSInterruptException: - pass + main() diff --git a/ros/perceptions/speech_to_text/scripts/whisper_speech_to_text_node.py b/ros/perceptions/speech_to_text/scripts/whisper_speech_to_text_node.py index 1f11e34f..13062147 100755 --- a/ros/perceptions/speech_to_text/scripts/whisper_speech_to_text_node.py +++ b/ros/perceptions/speech_to_text/scripts/whisper_speech_to_text_node.py @@ -8,11 +8,13 @@ from faster_whisper import WhisperModel -import rospy -from speech_to_text.msg import Transcript +import rclpy +import rclpy.node + +from perception_msgs.msg import Transcript from audio_utils import get_format_information, convert_audio_data_to_numpy_frames -from audio_utils.msg import AudioFrame, VoiceActivity +from audio_utils_msgs.msg import AudioFrame, VoiceActivity import hbba_lite @@ -22,15 +24,17 @@ SUPPORTED_SAMPLING_FREQUENCY = 16000 -class WhisperSpeechToTextNode: +class WhisperSpeechToTextNode(rclpy.node.Node): def __init__(self): - self._language = rospy.get_param('~language') - self._model_size = rospy.get_param('~model_size') - self._device = rospy.get_param('~device') - self._compute_type = rospy.get_param('~compute_type') + super().__init__('whisper_speech_to_text_node') + + self._language = self.declare_parameter('language', 'en').get_parameter_value().string_value + self._model_size = self.declare_parameter('model_size', 'base.en').get_parameter_value().string_value + self._device = self.declare_parameter('device', 'cpu').get_parameter_value().string_value + self._compute_type = self.declare_parameter('compute_type', 'float32').get_parameter_value().string_value - self._prebuffering_frame_count = rospy.get_param('~prebuffering_frame_count', 4) - self._minimum_voice_sequence_size = rospy.get_param('~minimum_voice_sequence_size', 8000) + self._prebuffering_frame_count = self.declare_parameter('prebuffering_frame_count', 4).get_parameter_value().integer_value + self._minimum_voice_sequence_size = self.declare_parameter('minimum_voice_sequence_size', 8000).get_parameter_value().integer_value if self._language not in SUPPORTED_LANGUAGES: raise ValueError(f'Invalid language ({self._language})') @@ -38,15 +42,12 @@ def __init__(self): self._model = WhisperModel(self._model_size, device=self._device, compute_type=self._compute_type) self._is_voice = False - self._frames_lock = threading.Lock() self._frames = [] self._voice_sequence_queue = queue.Queue() - rospy.on_shutdown(self._shutdown_cb) - - self._text_pub = rospy.Publisher('transcript', Transcript, queue_size=10) - self._voice_activity_pub = rospy.Subscriber('voice_activity', VoiceActivity, self._voice_activity_cb, queue_size=10) - self._audio_sub = hbba_lite.OnOffHbbaSubscriber('audio_in', AudioFrame, self._audio_cb, queue_size=10) + self._text_pub = self.create_publisher(Transcript, 'transcript', 10) + self._voice_activity_pub = self.create_subscription(VoiceActivity, 'voice_activity', self._voice_activity_cb, 10) + self._audio_sub = hbba_lite.OnOffHbbaSubscriber(self, AudioFrame, 'audio_in', self._audio_cb, 10) self._audio_sub.on_filter_state_changed(self._filter_state_changed_cb) def _voice_activity_cb(self, msg): @@ -58,17 +59,16 @@ def _voice_activity_cb(self, msg): def _audio_cb(self, msg): if msg.channel_count != SUPPORTED_CHANNEL_COUNT or msg.sampling_frequency != SUPPORTED_SAMPLING_FREQUENCY: - rospy.logerr('Invalid audio frame (msg.channel_count={}, msg.sampling_frequency={}})' + self.get_logger().error('Invalid audio frame (msg.channel_count={}, msg.sampling_frequency={}})' .format(msg.channel_count, msg.sampling_frequency)) return input_format_information = get_format_information(msg.format) frame = convert_audio_data_to_numpy_frames(input_format_information, msg.channel_count, msg.data)[0] - with self._frames_lock: - self._frames.append(frame.astype(np.float32)) - if not self._is_voice and len(self._frames) > self._prebuffering_frame_count: - self._frames = self._frames[-self._prebuffering_frame_count:] + self._frames.append(frame.astype(np.float32)) + if not self._is_voice and len(self._frames) > self._prebuffering_frame_count: + self._frames = self._frames[-self._prebuffering_frame_count:] def _filter_state_changed_cb(self, previous_is_filtering_all_messages, new_is_filtering_all_messages): if not previous_is_filtering_all_messages and new_is_filtering_all_messages: @@ -76,18 +76,24 @@ def _filter_state_changed_cb(self, previous_is_filtering_all_messages, new_is_fi self._put_frames_in_voice_sequence_queue() def _put_frames_in_voice_sequence_queue(self): - with self._frames_lock: - if len(self._frames) > 0: - self._voice_sequence_queue.put(np.concatenate(self._frames)) - self._frames.clear() - - def _shutdown_cb(self): - self._voice_sequence_queue.put(None) + if len(self._frames) > 0: + self._voice_sequence_queue.put(np.concatenate(self._frames)) + self._frames.clear() def run(self): + speech_to_text_thread = threading.Thread(target=self._speech_to_text_thread_run) + speech_to_text_thread.start() + + try: + rclpy.spin(self) + finally: + self._voice_sequence_queue.put(None) + speech_to_text_thread.join() + + def _speech_to_text_thread_run(self): self._warm_up_model() - while not rospy.is_shutdown(): + while rclpy.ok(): voice_sequence = self._voice_sequence_queue.get() if voice_sequence is None: break @@ -115,13 +121,18 @@ def _warm_up_model(self): def main(): - rospy.init_node('whisper_speech_to_text_node') + rclpy.init() whisper_speech_to_text_node = WhisperSpeechToTextNode() - whisper_speech_to_text_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + whisper_speech_to_text_node.run() + except KeyboardInterrupt: pass + finally: + whisper_speech_to_text_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/perceptions/video_analyzer/CMakeLists.txt b/ros/perceptions/video_analyzer/CMakeLists.txt index 5999dbb2..93934627 100644 --- a/ros/perceptions/video_analyzer/CMakeLists.txt +++ b/ros/perceptions/video_analyzer/CMakeLists.txt @@ -1,219 +1,46 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(video_analyzer) -## Compile as C++11, supported in ROS Kinetic and newer -# add_compile_options(-std=c++11) -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - dnn_utils - message_generation - rospy - std_msgs - geometry_msgs - sensor_msgs - visualization_msgs - hbba_lite -) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -add_message_files( - FILES - VideoAnalysis.msg - VideoAnalysisObject.msg - SemanticSegmentation.msg -) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -generate_messages( - DEPENDENCIES - std_msgs - geometry_msgs - sensor_msgs - visualization_msgs - hbba_lite -) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( -# INCLUDE_DIRS include -# LIBRARIES video_analyzer -# CATKIN_DEPENDS dnn_utils message_generation rospy std_msgs -# DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( -# include - ${catkin_INCLUDE_DIRS} -) - -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/video_analyzer.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -# add_executable(${PROJECT_NAME}_node src/video_analyzer_node.cpp) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -# target_link_libraries(${PROJECT_NAME}_node -# ${catkin_LIBRARIES} -# ) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -catkin_install_python(PROGRAMS +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclpy REQUIRED) +find_package(dnn_utils REQUIRED) +find_package(std_msgs REQUIRED) +find_package(sensor_msgs REQUIRED) +find_package(geometry_msgs REQUIRED) +find_package(visualization_msgs REQUIRED) +find_package(cv_bridge REQUIRED) +find_package(hbba_lite REQUIRED) +find_package(perception_msgs REQUIRED) + +# Python Librairies +ament_python_install_package(${PROJECT_NAME}) + +# Python Nodes +install(PROGRAMS scripts/video_analysis_markers_node.py scripts/video_analysis_visualizer_node.py scripts/video_analyzer_2d_node.py scripts/video_analyzer_3d_node.py - DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} + DESTINATION lib/${PROJECT_NAME} ) -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_video_analyzer.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() +# Launch files +install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}) -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/perceptions/video_analyzer/README.md b/ros/perceptions/video_analyzer/README.md index e2a49813..23e55bdc 100644 --- a/ros/perceptions/video_analyzer/README.md +++ b/ros/perceptions/video_analyzer/README.md @@ -7,30 +7,30 @@ This node detects objects. If the audio contains a person, it estimates the pose This node uses RGB images, so the 3D positions are not set. #### Parameters - - `use_descriptor_yolo` (bool): Indicates to use the network extracting an object embedding or not. + - `use_descriptor_yolo` (bool): Indicates to use the network extracting an object embedding or not. The default value is false. - `yolo_model` (string): If descriptor_yolo_v4 is not used, it indicates which model to use for YOLO (yolo_v4_coco, yolo_v4_tiny_coco, yolo_v7_coco, yolo_v7_tiny_coco or yolo_v7_objects365). - If descriptor_yolo is used, it indicates which model to use for Descriptor-YOLO (yolo_v4_tiny_coco, yolo_v7_coco or yolo_v7_objects365). - - `confidence_threshold` (double): The object confidence threshold. - - `nms_threshold` (double): The Non-Maximum Suppresion threshold. - - `person_probability_threshold` (double): The person confidence threshold. - - `pose_confidence_threshold` (double): The pose key point confidence threshold. - - `inference_type` (string): Indicates where to run the neural network (cpu, torch_gpu or trt_gpu). - - `pose_enabled` (bool): Indicates to estimate the pose of the people. - - `face_descriptor_enabled` (bool): Indicates to extract an embedding for each face. The pose estimation must be enabled when the face embedding is enabled. - - `semantic_segmentation_enabled` (bool): Indicates to perform semantic segmentation. - - `semantic_segmentation_dataset` (string): Indicates which model to use semantic segmentation (coco, kitchen_open_images or person_other_open_images). - - `cropped_image_enabled` (bool): Indicates to publish cropped images for each object, pose and face. + If descriptor_yolo is used, it indicates which model to use for Descriptor-YOLO (yolo_v4_tiny_coco, yolo_v7_coco or yolo_v7_objects365). The default value is yolo_v7_coco. + - `confidence_threshold` (double): The object confidence threshold. The default value is 0.5. + - `nms_threshold` (double): The Non-Maximum Suppresion threshold. The default value is 0.5. + - `person_probability_threshold` (double): The person confidence threshold. The default value is 0.5. + - `pose_confidence_threshold` (double): The pose key point confidence threshold. The default value is 0.4. + - `inference_type` (string): Indicates where to run the neural network (cpu, torch_gpu or trt_gpu). The default value is cpu. + - `pose_enabled` (bool): Indicates to estimate the pose of the people. The default value is true. + - `face_descriptor_enabled` (bool): Indicates to extract an embedding for each face. The pose estimation must be enabled when the face embedding is enabled. The default value is true. + - `semantic_segmentation_enabled` (bool): Indicates to perform semantic segmentation. The default value is false. + - `semantic_segmentation_dataset` (string): Indicates which model to use semantic segmentation (coco, kitchen_open_images or person_other_open_images). The default value is coco. + - `cropped_image_enabled` (bool): Indicates to publish cropped images for each object, pose and face. The default value is false. #### Subscribed Topics - - `image_raw` ([sensor_msgs/Image](http://docs.ros.org/en/noetic/api/sensor_msgs/html/msg/Image.html)): The color image. + - `image_raw` ([sensor_msgs/Image](https://docs.ros.org/en/humble/p/sensor_msgs/interfaces/msg/Image.html)): The color image. #### Published Topics - - `video_analysis` ([video_analyzer/VideoAnalysis](msg/VideoAnalysis.msg)): The video analysis containing the detected objects. - - `analysed_image` ([sensor_msgs/Image](http://docs.ros.org/en/noetic/api/sensor_msgs/html/msg/Image.html)): A rendering of the video analysis. + - `video_analysis` ([perception_msgs/VideoAnalysis](../perception_msgs/msg/VideoAnalysis.msg)): The video analysis containing the detected objects. + - `analysed_image` ([sensor_msgs/Image](https://docs.ros.org/en/humble/p/sensor_msgs/interfaces/msg/Image.html)): A rendering of the video analysis. #### Services - - `image_raw/filter_state` ([hbba_lite/SetThrottlingFilterState](../../hbba_lite/srv/SetThrottlingFilterState.srv)) The HBBA filter state service to enable, disable or throttle the processing. - - `analysed_image/filter_state` ([hbba_lite/SetOnOffFilterState](../../hbba_lite/srv/SetOnOffFilterState.srv)) The HBBA filter state service to enable or disable the topic `analysed_image`. + - `image_raw/filter_state` ([hbba_lite_srvs/SetThrottlingFilterState](../../utils/hbba_lite/hbba_lite_srvs/srv/SetThrottlingFilterState.srv)) The HBBA filter state service to enable, disable or throttle the processing. + - `analysed_image/filter_state` ([hbba_lite_srvs/SetOnOffFilterState](../../utils/hbba_lite/hbba_lite_srvs/srv/SetOnOffFilterState.srv)) The HBBA filter state service to enable or disable the topic `analysed_image`. ### `video_analyzer_3d_node.py` @@ -38,48 +38,48 @@ This node detects objects. If the audio contains a person, it estimates the pose This node uses RGB-D images, so the 3D positions are set. #### Parameters - - `use_descriptor_yolo` (bool): Indicates to use the network extracting an object embedding or not. + - `use_descriptor_yolo` (bool): Indicates to use the network extracting an object embedding or not. The default value is false. - `yolo_model` (string): If descriptor_yolo_v4 is not used, it indicates which model to use for YOLO (yolo_v4_coco, yolo_v4_tiny_coco, yolo_v7_coco, yolo_v7_tiny_coco or yolo_v7_objects365). - If descriptor_yolo is used, it indicates which model to use for Descriptor-YOLO (yolo_v4_tiny_coco, yolo_v7_coco or yolo_v7_objects365). - - `confidence_threshold` (double): The object confidence threshold. - - `nms_threshold` (double): The Non-Maximum Suppresion threshold. - - `person_probability_threshold` (double): The person confidence threshold. - - `pose_confidence_threshold` (double): The pose key point confidence threshold. - - `inference_type` (string): Indicates where to run the neural network (cpu, torch_gpu or trt_gpu). - - `pose_enabled` (bool): Indicates to estimate the pose of the people. - - `face_descriptor_enabled` (bool): Indicates to extract an embedding for each face. The pose estimation must be enabled when the face embedding is enabled. - - `semantic_segmentation_enabled` (bool): Indicates to perform semantic segmentation. - - `semantic_segmentation_dataset` (string): Indicates which model to use semantic segmentation (coco, kitchen_open_images or person_other_open_images). - - `cropped_image_enabled` (bool): Indicates to publish cropped images for each object, pose and face. - - `depth_mean_offset` (int): The rectangle offset when calulating the depth of the object. + If descriptor_yolo is used, it indicates which model to use for Descriptor-YOLO (yolo_v4_tiny_coco, yolo_v7_coco or yolo_v7_objects365). The default value is yolo_v7_coco. + - `confidence_threshold` (double): The object confidence threshold. The default value is 0.5. + - `nms_threshold` (double): The Non-Maximum Suppresion threshold. The default value is 0.5. + - `person_probability_threshold` (double): The person confidence threshold. The default value is 0.5. + - `pose_confidence_threshold` (double): The pose key point confidence threshold. The default value is 0.4. + - `inference_type` (string): Indicates where to run the neural network (cpu, torch_gpu or trt_gpu). The default value is cpu. + - `pose_enabled` (bool): Indicates to estimate the pose of the people. The default value is true. + - `face_descriptor_enabled` (bool): Indicates to extract an embedding for each face. The pose estimation must be enabled when the face embedding is enabled. The default value is true. + - `semantic_segmentation_enabled` (bool): Indicates to perform semantic segmentation. The default value is false. + - `semantic_segmentation_dataset` (string): Indicates which model to use semantic segmentation (coco, kitchen_open_images or person_other_open_images). The default value is coco. + - `cropped_image_enabled` (bool): Indicates to publish cropped images for each object, pose and face. The default value is false. + - `depth_mean_offset` (int): The rectangle offset when calulating the depth of the object. The deault value is 1. #### Subscribed Topics - - `image_raw` ([sensor_msgs/Image](http://docs.ros.org/en/noetic/api/sensor_msgs/html/msg/Image.html)): The color image. - - `depth_image_raw` ([sensor_msgs/Image](http://docs.ros.org/en/noetic/api/sensor_msgs/html/msg/Image.html)): The depth image. - - `depth_camera_info` ([sensor_msgs/CameraInfo](http://docs.ros.org/en/noetic/api/sensor_msgs/html/msg/CameraInfo.html)): The depth camera info used to preject 2D point in 3D. + - `image_raw` ([sensor_msgs/Image](https://docs.ros.org/en/humble/p/sensor_msgs/interfaces/msg/Image.html)): The color image. + - `depth_image_raw` ([sensor_msgs/Image](https://docs.ros.org/en/humble/p/sensor_msgs/interfaces/msg/Image.html)): The depth image. + - `depth_camera_info` ([sensor_msgs/CameraInfo](https://docs.ros.org/en/humble/p/sensor_msgs/interfaces/msg/CameraInfo.html)): The depth camera info used to preject 2D point in 3D. #### Published Topics - - `video_analysis` ([video_analyzer/VideoAnalysis](msg/VideoAnalysis.msg)): The video analysis containing the detected objects. - - `analysed_image` ([sensor_msgs/Image](http://docs.ros.org/en/noetic/api/sensor_msgs/html/msg/Image.html)): A rendering of the video analysis. + - `video_analysis` ([perception_msgs/VideoAnalysis](../perception_msgs/msg/VideoAnalysis.msg)): The video analysis containing the detected objects. + - `analysed_image` ([sensor_msgs/Image](https://docs.ros.org/en/humble/p/sensor_msgs/interfaces/msg/Image.html)): A rendering of the video analysis. #### Services - - `image_raw/filter_state` ([hbba_lite/SetThrottlingFilterState](../../hbba_lite/srv/SetThrottlingFilterState.srv)) The HBBA filter state service to enable, disable or throttle the processing. - - `analysed_image/filter_state` ([hbba_lite/SetOnOffFilterState](../../hbba_lite/srv/SetOnOffFilterState.srv)) The HBBA filter state service to enable or disable the topic `analysed_image`. + - `image_raw/filter_state` ([hbba_lite_srvs/SetThrottlingFilterState](../../utils/hbba_lite/hbba_lite_srvs/srv/SetThrottlingFilterState.srv)) The HBBA filter state service to enable, disable or throttle the processing. + - `analysed_image/filter_state` ([hbba_lite_srvs/SetOnOffFilterState](../../utils/hbba_lite/hbba_lite_srvs/srv/SetOnOffFilterState.srv)) The HBBA filter state service to enable or disable the topic `analysed_image`. ### `video_analysis_visualizer_node.py` This node create a mosaic containing the objects in the video analysis. #### Subscribed Topics - - `video_analysis` ([video_analyzer/VideoAnalysis](msg/VideoAnalysis.msg)): The video analysis containing the detected objects. + - `video_analysis` ([perception_msgs/VideoAnalysis](../perception_msgs/msg/VideoAnalysis.msg)): The video analysis containing the detected objects. #### Published Topics - - `video_analysis_mosaic` ([sensor_msgs/Image](http://docs.ros.org/en/noetic/api/sensor_msgs/html/msg/Image.html)): The mosaic containing the objects in the video analysis. + - `video_analysis_mosaic` ([sensor_msgs/Image](https://docs.ros.org/en/humble/p/sensor_msgs/interfaces/msg/Image.html)): The mosaic containing the objects in the video analysis. ### `video_analysis_markers_node.py` This node create a marker array for the objects in the video analysis. #### Subscribed Topics - - `video_analysis` ([video_analyzer/VideoAnalysis](msg/VideoAnalysis.msg)): The video analysis containing the detected objects. + - `video_analysis` ([perception_msgs/VideoAnalysis](../perception_msgs/msg/VideoAnalysis.msg)): The video analysis containing the detected objects. #### Published Topics - - `video_analysis_markers` ([visualization_msgs/MarkerArray](http://docs.ros.org/en/noetic/api/visualization_msgs/html/msg/MarkerArray.html)): The marker array for the objects in the video analysis. + - `video_analysis_markers` ([visualization_msgs/MarkerArray](https://docs.ros.org/en/humble/p/visualization_msgs/interfaces/msg/MarkerArray.html)): The marker array for the objects in the video analysis. diff --git a/ros/t_top/launch/tests/test_video_analyzer_2d_node.launch b/ros/perceptions/video_analyzer/launch/test_video_analyzer_2d_node.launch.xml similarity index 74% rename from ros/t_top/launch/tests/test_video_analyzer_2d_node.launch rename to ros/perceptions/video_analyzer/launch/test_video_analyzer_2d_node.launch.xml index b338b595..110dc72a 100644 --- a/ros/t_top/launch/tests/test_video_analyzer_2d_node.launch +++ b/ros/perceptions/video_analyzer/launch/test_video_analyzer_2d_node.launch.xml @@ -1,14 +1,14 @@ - + - + - + @@ -19,8 +19,7 @@ - - + diff --git a/ros/perceptions/video_analyzer/launch/test_video_analyzer_3d_node.launch.xml b/ros/perceptions/video_analyzer/launch/test_video_analyzer_3d_node.launch.xml new file mode 100644 index 00000000..f403db90 --- /dev/null +++ b/ros/perceptions/video_analyzer/launch/test_video_analyzer_3d_node.launch.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ros/perceptions/video_analyzer/msg/VideoAnalysis.msg b/ros/perceptions/video_analyzer/msg/VideoAnalysis.msg deleted file mode 100644 index 5ec48174..00000000 --- a/ros/perceptions/video_analyzer/msg/VideoAnalysis.msg +++ /dev/null @@ -1,6 +0,0 @@ -std_msgs/Header header - -bool contains_3d_positions -video_analyzer/VideoAnalysisObject[] objects -video_analyzer/SemanticSegmentation[] semantic_segmentation -float32 processing_time_s diff --git a/ros/perceptions/video_analyzer/package.xml b/ros/perceptions/video_analyzer/package.xml index be921070..42f3dba5 100644 --- a/ros/perceptions/video_analyzer/package.xml +++ b/ros/perceptions/video_analyzer/package.xml @@ -1,87 +1,31 @@ - + + video_analyzer 0.0.0 The video_analyzer package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rclpy + dnn_utils + std_msgs + sensor_msgs + geometry_msgs + visualization_msgs + cv_bridge + hbba_lite + perception_msgs - - - - TODO + rosidl_default_runtime + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - dnn_utils - message_generation - rospy - std_msgs - geometry_msgs - message_filters - sensor_msgs - visualization_msgs - cv_bridge - hbba_lite - dnn_utils - rospy - std_msgs - geometry_msgs - message_filters - sensor_msgs - visualization_msgs - cv_bridge - hbba_lite - dnn_utils - rospy - std_msgs - geometry_msgs - message_filters - sensor_msgs - visualization_msgs - cv_bridge - hbba_lite - - - - - + ament_cmake diff --git a/ros/perceptions/video_analyzer/scripts/video_analysis_markers_node.py b/ros/perceptions/video_analyzer/scripts/video_analysis_markers_node.py index d9a3229a..b931310b 100755 --- a/ros/perceptions/video_analyzer/scripts/video_analysis_markers_node.py +++ b/ros/perceptions/video_analyzer/scripts/video_analysis_markers_node.py @@ -1,15 +1,18 @@ #!/usr/bin/env python3 -import rospy +import rclpy +import rclpy.node from visualization_msgs.msg import Marker from visualization_msgs.msg import MarkerArray -from video_analyzer.msg import VideoAnalysis +from perception_msgs.msg import VideoAnalysis -class VideoAnalysisMarkersNode: +class VideoAnalysisMarkersNode(rclpy.node.Node): def __init__(self): - self._video_analysis_sub = rospy.Subscriber('video_analysis', VideoAnalysis, self._video_analysis_cb, queue_size=10) - self._video_analysis_markers_pub = rospy.Publisher('video_analysis_markers', MarkerArray, queue_size=10) + super().__init__('video_analysis_markers_node') + + self._video_analysis_sub = self.create_subscription(VideoAnalysis, 'video_analysis', self._video_analysis_cb, 10) + self._video_analysis_markers_pub = self.create_publisher(MarkerArray, 'video_analysis_markers', 10) def _delete_markers(self): markerArray = MarkerArray() @@ -19,6 +22,8 @@ def _delete_markers(self): self._video_analysis_markers_pub.publish(markerArray) def _create_marker(self, header, tag, type, pose, ID, scale, rgb, points=[], name=''): + scale = float(scale) + marker = Marker() marker.header.stamp = header.stamp marker.header.frame_id = header.frame_id @@ -27,17 +32,17 @@ def _create_marker(self, header, tag, type, pose, ID, scale, rgb, points=[], nam marker.type = type marker.action = Marker.ADD marker.pose.position = pose - marker.pose.orientation.x = 0 - marker.pose.orientation.y = 0 - marker.pose.orientation.z = 0 - marker.pose.orientation.w = 1 + marker.pose.orientation.x = 0.0 + marker.pose.orientation.y = 0.0 + marker.pose.orientation.z = 0.0 + marker.pose.orientation.w = 1.0 marker.scale.x = scale marker.scale.y = scale marker.scale.z = scale marker.color.a = 1.0 - marker.color.r = rgb[0] - marker.color.g = rgb[1] - marker.color.b = rgb[2] + marker.color.r = float(rgb[0]) + marker.color.g = float(rgb[1]) + marker.color.b = float(rgb[2]) marker.points = points marker.text = name @@ -45,7 +50,7 @@ def _create_marker(self, header, tag, type, pose, ID, scale, rgb, points=[], nam def _video_analysis_cb(self, msg): if not msg.contains_3d_positions: - rospy.logerr('The video analysis must contain 3d positions.') + self.get_logger().error('The video analysis must contain 3d positions.') return self._delete_markers() @@ -79,17 +84,22 @@ def _video_analysis_cb(self, msg): self._video_analysis_markers_pub.publish(markerArray) def run(self): - rospy.spin() + rclpy.spin(self) def main(): - rospy.init_node('video_analysis_markers_node') + rclpy.init() video_analysis_markers_node = VideoAnalysisMarkersNode() - video_analysis_markers_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + video_analysis_markers_node.run() + except KeyboardInterrupt: pass + finally: + video_analysis_markers_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/perceptions/video_analyzer/scripts/video_analysis_visualizer_node.py b/ros/perceptions/video_analyzer/scripts/video_analysis_visualizer_node.py index cc4c21e4..0fb88b1c 100755 --- a/ros/perceptions/video_analyzer/scripts/video_analysis_visualizer_node.py +++ b/ros/perceptions/video_analyzer/scripts/video_analysis_visualizer_node.py @@ -1,15 +1,15 @@ #!/usr/bin/env python3 -import traceback - import numpy as np -import cv2 -import rospy +import rclpy +import rclpy.node + + from cv_bridge import CvBridge from sensor_msgs.msg import Image -from video_analyzer.msg import VideoAnalysis +from perception_msgs.msg import VideoAnalysis def concatenate_horizontal(image0, image1): @@ -32,12 +32,14 @@ def concatenate_vertical(image0, image1): return output -class VideoAnalysisVisualizerNode: +class VideoAnalysisVisualizerNode(rclpy.node.Node): def __init__(self): + super().__init__('video_analysis_visualizer_node') + self._cv_bridge = CvBridge() - self._video_analysis_sub = rospy.Subscriber('video_analysis', VideoAnalysis, self._video_analysis_cb, queue_size=10) - self._video_analysis_mosaic_pub = rospy.Publisher('video_analysis_mosaic', Image, queue_size=10) + self._video_analysis_sub = self.create_subscription(VideoAnalysis, 'video_analysis', self._video_analysis_cb, 10) + self._video_analysis_mosaic_pub = self.create_publisher(Image, 'video_analysis_mosaic', 10) def _video_analysis_cb(self, msg): objects = msg.objects @@ -63,27 +65,33 @@ def _concatenate_object_images(self, o): face_image = None if len(o.person_pose_2d) > 0: pose_image = self._cv_bridge.imgmsg_to_cv2(o.person_pose_image, 'rgb8') - face_image = self._cv_bridge.imgmsg_to_cv2(o.face_image, 'rgb8') - output = concatenate_horizontal(object_image, pose_image) - output = concatenate_horizontal(output, face_image) + + if len(o.face_descriptor) > 0: + face_image = self._cv_bridge.imgmsg_to_cv2(o.face_image, 'rgb8') + output = concatenate_horizontal(output, face_image) else: output = object_image return output def run(self): - rospy.spin() + rclpy.spin(self) def main(): - rospy.init_node('video_analysis_visualizer_node') + rclpy.init() video_analysis_visualizer_node = VideoAnalysisVisualizerNode() - video_analysis_visualizer_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + video_analysis_visualizer_node.run() + except KeyboardInterrupt: pass + finally: + video_analysis_visualizer_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/perceptions/video_analyzer/scripts/video_analyzer_2d_node.py b/ros/perceptions/video_analyzer/scripts/video_analyzer_2d_node.py index 822aa381..116cd82a 100755 --- a/ros/perceptions/video_analyzer/scripts/video_analyzer_2d_node.py +++ b/ros/perceptions/video_analyzer/scripts/video_analyzer_2d_node.py @@ -2,11 +2,12 @@ import traceback from datetime import datetime -import rospy + +import rclpy from sensor_msgs.msg import Image from geometry_msgs.msg import Point -from video_analyzer.msg import VideoAnalysis, VideoAnalysisObject +from perception_msgs.msg import VideoAnalysis, VideoAnalysisObject import hbba_lite @@ -15,8 +16,8 @@ class VideoAnalyzer2dNode(VideoAnalyzerNode): def __init__(self): - super().__init__() - self._image_sub = hbba_lite.ThrottlingHbbaSubscriber('image_raw', Image, self._image_cb, queue_size=1) + super().__init__('video_analyzer_2d_node') + self._image_sub = hbba_lite.ThrottlingHbbaSubscriber(self, Image, 'image_raw', self._image_cb, 1) def _image_cb(self, color_image_msg): try: @@ -30,7 +31,7 @@ def _image_cb(self, color_image_msg): self._video_analysis_pub.publish(video_analysis_msg) self._publish_analysed_image(color_image, color_image_msg.header, object_analyses) except Exception as e: - rospy.logerr(f'Image analysis error: {e} \n {traceback.format_exc()}') + self.get_logger().error(f'Image analysis error: {e} \n {traceback.format_exc()}') def _analysis_to_msg(self, object_analyses, semantic_segmentation, header, color_image): image_height, image_width, _ = color_image.shape @@ -77,13 +78,18 @@ def _object_analysis_to_msg(self, object_analysis, image_height, image_width): def main(): - rospy.init_node('video_analyzer_2d_node') + rclpy.init() video_analyzer_node = VideoAnalyzer2dNode() - video_analyzer_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + video_analyzer_node.run() + except KeyboardInterrupt: pass + finally: + video_analyzer_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/perceptions/video_analyzer/scripts/video_analyzer_3d_node.py b/ros/perceptions/video_analyzer/scripts/video_analyzer_3d_node.py index 39d95bae..ba495a2d 100755 --- a/ros/perceptions/video_analyzer/scripts/video_analyzer_3d_node.py +++ b/ros/perceptions/video_analyzer/scripts/video_analyzer_3d_node.py @@ -2,12 +2,12 @@ import traceback from datetime import datetime -import rospy +import rclpy import message_filters from sensor_msgs.msg import Image, CameraInfo from geometry_msgs.msg import Point -from video_analyzer.msg import VideoAnalysis, VideoAnalysisObject +from perception_msgs.msg import VideoAnalysis, VideoAnalysisObject import hbba_lite @@ -19,18 +19,19 @@ class VideoAnalyzer3dNode(VideoAnalyzerNode): def __init__(self): - super().__init__() - self._depth_mean_offset = rospy.get_param('~depth_mean_offset', 1) + super().__init__('video_analyzer_3d_node') - color_image_sub = message_filters.Subscriber('color_image_raw', Image) - depth_image_sub = message_filters.Subscriber('depth_image_raw', Image) - depth_camera_info_sub = message_filters.Subscriber('depth_camera_info', CameraInfo) - self._image_ts = hbba_lite.ThrottlingHbbaApproximateTimeSynchronizer([color_image_sub, depth_image_sub, depth_camera_info_sub], + self._depth_mean_offset = self.declare_parameter('depth_mean_offset', 1).get_parameter_value().integer_value + + color_image_sub = message_filters.Subscriber(self, Image, 'color_image_raw') + depth_image_sub = message_filters.Subscriber(self, Image, 'depth_image_raw') + depth_camera_info_sub = message_filters.Subscriber(self, CameraInfo, 'depth_camera_info') + self._image_ts = hbba_lite.ThrottlingHbbaApproximateTimeSynchronizer(self, [color_image_sub, depth_image_sub, depth_camera_info_sub], 1, 0.03, self._image_cb, 'image_raw/filter_state') def _image_cb(self, color_image_msg, depth_image_msg, depth_camera_info): if depth_image_msg.encoding != '16UC1': - rospy.logerr('Invalid depth image encoding') + self.get_logger().error('Invalid depth image encoding') try: start_time = datetime.now() @@ -46,13 +47,12 @@ def _image_cb(self, color_image_msg, depth_image_msg, depth_camera_info): self._video_analysis_pub.publish(video_analysis_msg) self._publish_analysed_image(color_image, color_image_msg.header, object_analyses) except Exception as e: - rospy.logerr(f'Image analysis error: {e} \n {traceback.format_exc()}') + self.get_logger().error(f'Image analysis error: {e} \n {traceback.format_exc()}') def _analysis_to_msg(self, object_analyses, semantic_segmentation, header, color_image, depth_image, depth_camera_info): image_height, image_width, _ = color_image.shape msg = VideoAnalysis() - msg.header.seq = header.seq msg.header.stamp = header.stamp msg.header.frame_id = depth_camera_info.header.frame_id msg.contains_3d_positions = True @@ -113,7 +113,7 @@ def _project_2d_to_3d(self, x, y, depth_image, depth_camera_info): y1 = int(y + self._depth_mean_offset) depth_pixels = depth_image[y0:y1, x0:x1] depth = depth_pixels[depth_pixels != 0].mean() - K = depth_camera_info.K + K = depth_camera_info.k point = Point() point.x = (x - K[2]) * depth / K[0] * MM_TO_M @@ -123,13 +123,18 @@ def _project_2d_to_3d(self, x, y, depth_image, depth_camera_info): def main(): - rospy.init_node('video_analyzer_3d_node') + rclpy.init() video_analyzer_node = VideoAnalyzer3dNode() - video_analyzer_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + video_analyzer_node.run() + except KeyboardInterrupt: pass + finally: + video_analyzer_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/perceptions/video_analyzer/setup.py b/ros/perceptions/video_analyzer/setup.py deleted file mode 100644 index 4047b1b0..00000000 --- a/ros/perceptions/video_analyzer/setup.py +++ /dev/null @@ -1,12 +0,0 @@ -## ! DO NOT MANUALLY INVOKE THIS setup.py, USE CATKIN INSTEAD - -from setuptools import setup -from catkin_pkg.python_setup import generate_distutils_setup - -# fetch values from package.xml -setup_args = generate_distutils_setup( - packages=['video_analyzer'], - package_dir={'': 'src'}, -) - -setup(**setup_args) diff --git a/ros/perceptions/video_analyzer/video_analyzer/__init__.py b/ros/perceptions/video_analyzer/video_analyzer/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/ros/perceptions/video_analyzer/src/video_analyzer/lib_video_analyzer_node.py b/ros/perceptions/video_analyzer/video_analyzer/lib_video_analyzer_node.py similarity index 85% rename from ros/perceptions/video_analyzer/src/video_analyzer/lib_video_analyzer_node.py rename to ros/perceptions/video_analyzer/video_analyzer/lib_video_analyzer_node.py index e45015e1..ecd0c453 100644 --- a/ros/perceptions/video_analyzer/src/video_analyzer/lib_video_analyzer_node.py +++ b/ros/perceptions/video_analyzer/video_analyzer/lib_video_analyzer_node.py @@ -6,12 +6,14 @@ import torch import torchvision.transforms.functional as F -import rospy +import rclpy +import rclpy.node + from cv_bridge import CvBridge from sensor_msgs.msg import Image from geometry_msgs.msg import Point -from video_analyzer.msg import VideoAnalysis, SemanticSegmentation +from perception_msgs.msg import VideoAnalysis, SemanticSegmentation from dnn_utils import DescriptorYolo, Yolo, PoseEstimator, FaceDescriptorExtractor, SemanticSegmentationNetwork import hbba_lite @@ -78,21 +80,23 @@ def __init__(self, descriptor, alignment_keypoint_count, sharpness_score, face_i self.face_image = face_image -class VideoAnalyzerNode: - def __init__(self): - self._use_descriptor_yolo = rospy.get_param('~use_descriptor_yolo') - self._yolo_model = rospy.get_param('~yolo_model', None) - self._confidence_threshold = rospy.get_param('~confidence_threshold') - self._nms_threshold = rospy.get_param('~nms_threshold') - self._person_probability_threshold = rospy.get_param('~person_probability_threshold') - self._pose_confidence_threshold = rospy.get_param('~pose_confidence_threshold') - self._inference_type = rospy.get_param('~inference_type', None) +class VideoAnalyzerNode(rclpy.node.Node): + def __init__(self, node_name): + super().__init__(node_name) + + self._use_descriptor_yolo = self.declare_parameter('use_descriptor_yolo', False).get_parameter_value().bool_value + self._yolo_model = self.declare_parameter('yolo_model', 'yolo_v7_coco').get_parameter_value().string_value + self._confidence_threshold = self.declare_parameter('confidence_threshold', 0.5).get_parameter_value().double_value + self._nms_threshold = self.declare_parameter('nms_threshold', 0.5).get_parameter_value().double_value + self._person_probability_threshold = self.declare_parameter('person_probability_threshold', 0.5).get_parameter_value().double_value + self._pose_confidence_threshold = self.declare_parameter('pose_confidence_threshold', 0.4).get_parameter_value().double_value + self._inference_type = self.declare_parameter('inference_type', 'cpu').get_parameter_value().string_value - self._pose_enabled = rospy.get_param('~pose_enabled', True) - self._face_descriptor_enabled = rospy.get_param('~face_descriptor_enabled', True) - self._semantic_segmentation_enabled = rospy.get_param('~semantic_segmentation_enabled', True) - self._semantic_segmentation_dataset = rospy.get_param('~semantic_segmentation_dataset', 'coco') - self._cropped_image_enabled = rospy.get_param('~cropped_image_enabled', True) + self._pose_enabled = self.declare_parameter('pose_enabled', True).get_parameter_value().bool_value + self._face_descriptor_enabled = self.declare_parameter('face_descriptor_enabled', True).get_parameter_value().bool_value + self._semantic_segmentation_enabled = self.declare_parameter('semantic_segmentation_enabled', False).get_parameter_value().bool_value + self._semantic_segmentation_dataset = self.declare_parameter('semantic_segmentation_dataset', 'coco').get_parameter_value().string_value + self._cropped_image_enabled = self.declare_parameter('cropped_image_enabled', False).get_parameter_value().bool_value if self._face_descriptor_enabled and not self._pose_enabled: raise ValueError('The pose estimation must be enabled when the face descriptor extraction is enabled.') @@ -116,8 +120,8 @@ def __init__(self): self._person_class_index = self._object_class_names.index('person') - self._video_analysis_pub = rospy.Publisher('video_analysis', VideoAnalysis, queue_size=10) - self._analysed_image_pub = hbba_lite.OnOffHbbaPublisher('analysed_image', Image, queue_size=10) + self._video_analysis_pub = self.create_publisher(VideoAnalysis, 'video_analysis', 10) + self._analysed_image_pub = hbba_lite.OnOffHbbaPublisher(self, Image, 'analysed_image', 10) self._cv_bridge = CvBridge() @@ -239,7 +243,7 @@ def _draw_person_pose(self, image, pose_coordinates, pose_confidence): cv2.line(image, (x0, y0), (x1, y1), (255, 255, 0), thickness=4) def run(self): - rospy.spin() + rclpy.spin(self) def convert_pose_coordinates_2d(pose_coordinates, image_width, image_height): diff --git a/ros/t_top/CMakeLists.txt b/ros/t_top/CMakeLists.txt index 9540744b..6dfd37c3 100644 --- a/ros/t_top/CMakeLists.txt +++ b/ros/t_top/CMakeLists.txt @@ -1,206 +1,43 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(t_top) -## Compile as C++11, supported in ROS Kinetic and newer -# add_compile_options(-std=c++11) - -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - rospy - daemon_ros_client -) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -# add_message_files( -# FILES -# Message1.msg -# Message2.msg -# ) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -# generate_messages( -# DEPENDENCIES -# geometry_msgs# nav_msgs# sensor_msgs# std_msgs -# ) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( - # INCLUDE_DIRS include - # LIBRARIES t_top - # CATKIN_DEPENDS geometry_msgs nav_msgs rospy sensor_msgs std_msgs tf - # DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( - # include - ${catkin_INCLUDE_DIRS} -) - -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/t_top.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -# add_executable(${PROJECT_NAME}_node src/t_top_node.cpp) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -# target_link_libraries(${PROJECT_NAME}_node -# ${catkin_LIBRARIES} -# ) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -catkin_install_python(PROGRAMS - scripts/head_roll_image_rotation_node.py - scripts/robot_status.py - DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclpy REQUIRED) +find_package(daemon_ros_client REQUIRED) +find_package(std_msgs REQUIRED) +find_package(geometry_msgs REQUIRED) +find_package(cv_bridge REQUIRED) +find_package(hbba_lite REQUIRED) + +# Python Librairies +ament_python_install_package(${PROJECT_NAME}) + +# Python Nodes +install(PROGRAMS + scripts/head_roll_image_rotation_node.py + scripts/robot_status.py + DESTINATION lib/${PROJECT_NAME} ) -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# +# Install the config +install(DIRECTORY config DESTINATION share/${PROJECT_NAME}) -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_t_top.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() +# Launch files +install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}) -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/t_top/calibration/.gitignore b/ros/t_top/calibration/.gitignore deleted file mode 100644 index 5d28c61c..00000000 --- a/ros/t_top/calibration/.gitignore +++ /dev/null @@ -1 +0,0 @@ -camera_2d_wide.yaml diff --git a/ros/t_top/config/configuration_16SoundsUSB.cfg b/ros/t_top/config/configuration_16SoundsUSB.cfg index ac5ccf9d..470250d2 100644 --- a/ros/t_top/config/configuration_16SoundsUSB.cfg +++ b/ros/t_top/config/configuration_16SoundsUSB.cfg @@ -35,8 +35,8 @@ general: size: #for fft calculation { - hopSize = 128; #shift size of the cross fft - frameSize = 256; #size of each fft of the cross fft + hopSize = 512; #shift size of the cross fft + frameSize = 1024; #size of each fft of the cross fft }; samplerate: diff --git a/ros/t_top/launch/behaviors.launch b/ros/t_top/launch/behaviors.launch deleted file mode 100644 index 832efac9..00000000 --- a/ros/t_top/launch/behaviors.launch +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ros/t_top/launch/behaviors.launch.xml b/ros/t_top/launch/behaviors.launch.xml new file mode 100644 index 00000000..66066f11 --- /dev/null +++ b/ros/t_top/launch/behaviors.launch.xml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ros/t_top/launch/behaviors/dance.launch b/ros/t_top/launch/behaviors/dance.launch deleted file mode 100644 index 3d1786b7..00000000 --- a/ros/t_top/launch/behaviors/dance.launch +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ros/t_top/launch/behaviors/dance.launch.xml b/ros/t_top/launch/behaviors/dance.launch.xml new file mode 100644 index 00000000..b548b521 --- /dev/null +++ b/ros/t_top/launch/behaviors/dance.launch.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ros/t_top/launch/behaviors/explore.launch b/ros/t_top/launch/behaviors/explore.launch.xml similarity index 56% rename from ros/t_top/launch/behaviors/explore.launch rename to ros/t_top/launch/behaviors/explore.launch.xml index 23d44dd2..99b76584 100644 --- a/ros/t_top/launch/behaviors/explore.launch +++ b/ros/t_top/launch/behaviors/explore.launch.xml @@ -1,9 +1,9 @@ - + - - + + diff --git a/ros/t_top/launch/behaviors/face.launch b/ros/t_top/launch/behaviors/face.launch deleted file mode 100644 index c31c710c..00000000 --- a/ros/t_top/launch/behaviors/face.launch +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/ros/t_top/launch/behaviors/face.launch.xml b/ros/t_top/launch/behaviors/face.launch.xml new file mode 100644 index 00000000..c3e608d3 --- /dev/null +++ b/ros/t_top/launch/behaviors/face.launch.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/ros/t_top/launch/behaviors/face_following.launch b/ros/t_top/launch/behaviors/face_following.launch.xml similarity index 69% rename from ros/t_top/launch/behaviors/face_following.launch rename to ros/t_top/launch/behaviors/face_following.launch.xml index 2e13abcd..6ced083a 100644 --- a/ros/t_top/launch/behaviors/face_following.launch +++ b/ros/t_top/launch/behaviors/face_following.launch.xml @@ -1,10 +1,10 @@ - + - - - + + + @@ -17,9 +17,9 @@ - - - + + + diff --git a/ros/t_top/launch/behaviors/gesture.launch b/ros/t_top/launch/behaviors/gesture.launch deleted file mode 100644 index c3671f1f..00000000 --- a/ros/t_top/launch/behaviors/gesture.launch +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/ros/t_top/launch/behaviors/gesture.launch.xml b/ros/t_top/launch/behaviors/gesture.launch.xml new file mode 100644 index 00000000..700df3a3 --- /dev/null +++ b/ros/t_top/launch/behaviors/gesture.launch.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/ros/t_top/launch/behaviors/led_animations.launch b/ros/t_top/launch/behaviors/led_animations.launch deleted file mode 100644 index 0f172f0e..00000000 --- a/ros/t_top/launch/behaviors/led_animations.launch +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/ros/t_top/launch/behaviors/led_animations.launch.xml b/ros/t_top/launch/behaviors/led_animations.launch.xml new file mode 100644 index 00000000..ec051ea0 --- /dev/null +++ b/ros/t_top/launch/behaviors/led_animations.launch.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/ros/t_top/launch/behaviors/led_emotions.launch b/ros/t_top/launch/behaviors/led_emotions.launch deleted file mode 100644 index 54f954cd..00000000 --- a/ros/t_top/launch/behaviors/led_emotions.launch +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/ros/t_top/launch/behaviors/led_emotions.launch.xml b/ros/t_top/launch/behaviors/led_emotions.launch.xml new file mode 100644 index 00000000..c98b35c6 --- /dev/null +++ b/ros/t_top/launch/behaviors/led_emotions.launch.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/ros/t_top/launch/behaviors/opentera.launch b/ros/t_top/launch/behaviors/opentera.launch.xml similarity index 57% rename from ros/t_top/launch/behaviors/opentera.launch rename to ros/t_top/launch/behaviors/opentera.launch.xml index 852094a8..78350212 100644 --- a/ros/t_top/launch/behaviors/opentera.launch +++ b/ros/t_top/launch/behaviors/opentera.launch.xml @@ -8,10 +8,19 @@ + + + + + + + + + - - - + + + @@ -20,47 +29,47 @@ - + - + - + + + - + - - - + + - - + - + - + - + - - + + - + @@ -69,7 +78,7 @@ - + @@ -82,14 +91,14 @@ - + - + - + @@ -99,7 +108,7 @@ - + @@ -109,10 +118,10 @@ - - - - + + + + diff --git a/ros/t_top/launch/behaviors/sound_following.launch b/ros/t_top/launch/behaviors/sound_following.launch.xml similarity index 66% rename from ros/t_top/launch/behaviors/sound_following.launch rename to ros/t_top/launch/behaviors/sound_following.launch.xml index 8416b186..8cf4eebe 100644 --- a/ros/t_top/launch/behaviors/sound_following.launch +++ b/ros/t_top/launch/behaviors/sound_following.launch.xml @@ -1,17 +1,17 @@ - + - - - + + + - + diff --git a/ros/t_top/launch/behaviors/sound_object_person_following.launch b/ros/t_top/launch/behaviors/sound_object_person_following.launch.xml similarity index 69% rename from ros/t_top/launch/behaviors/sound_object_person_following.launch rename to ros/t_top/launch/behaviors/sound_object_person_following.launch.xml index ddecbea8..2b84e7f2 100644 --- a/ros/t_top/launch/behaviors/sound_object_person_following.launch +++ b/ros/t_top/launch/behaviors/sound_object_person_following.launch.xml @@ -2,11 +2,11 @@ - + - - - + + + @@ -14,12 +14,12 @@ - + - [all] + diff --git a/ros/t_top/launch/behaviors/sound_player.launch b/ros/t_top/launch/behaviors/sound_player.launch.xml similarity index 63% rename from ros/t_top/launch/behaviors/sound_player.launch rename to ros/t_top/launch/behaviors/sound_player.launch.xml index 4360c3a6..2f32d78d 100644 --- a/ros/t_top/launch/behaviors/sound_player.launch +++ b/ros/t_top/launch/behaviors/sound_player.launch.xml @@ -1,8 +1,8 @@ - + - + diff --git a/ros/t_top/launch/behaviors/talk.launch b/ros/t_top/launch/behaviors/talk.launch.xml similarity index 54% rename from ros/t_top/launch/behaviors/talk.launch rename to ros/t_top/launch/behaviors/talk.launch.xml index e3d99ef5..70644181 100644 --- a/ros/t_top/launch/behaviors/talk.launch +++ b/ros/t_top/launch/behaviors/talk.launch.xml @@ -3,13 +3,13 @@ - + - - - - - + + + + + @@ -19,7 +19,7 @@ - + diff --git a/ros/t_top/launch/behaviors/teleoperation.launch b/ros/t_top/launch/behaviors/teleoperation.launch.xml similarity index 63% rename from ros/t_top/launch/behaviors/teleoperation.launch rename to ros/t_top/launch/behaviors/teleoperation.launch.xml index 08b976e4..7a9387b6 100644 --- a/ros/t_top/launch/behaviors/teleoperation.launch +++ b/ros/t_top/launch/behaviors/teleoperation.launch.xml @@ -1,8 +1,8 @@ - - + + diff --git a/ros/t_top/launch/behaviors/too_close_reaction.launch b/ros/t_top/launch/behaviors/too_close_reaction.launch.xml similarity index 73% rename from ros/t_top/launch/behaviors/too_close_reaction.launch rename to ros/t_top/launch/behaviors/too_close_reaction.launch.xml index 54ce11de..cd33cbf2 100644 --- a/ros/t_top/launch/behaviors/too_close_reaction.launch +++ b/ros/t_top/launch/behaviors/too_close_reaction.launch.xml @@ -1,8 +1,8 @@ - + - + diff --git a/ros/t_top/launch/bringup.launch b/ros/t_top/launch/bringup.launch.xml similarity index 50% rename from ros/t_top/launch/bringup.launch rename to ros/t_top/launch/bringup.launch.xml index b645138f..9982c24d 100644 --- a/ros/t_top/launch/bringup.launch +++ b/ros/t_top/launch/bringup.launch.xml @@ -32,95 +32,97 @@ - + - + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - + + + - - + + diff --git a/ros/t_top/launch/opentera_teleop.launch b/ros/t_top/launch/opentera_teleop.launch deleted file mode 100644 index 16b9bcc8..00000000 --- a/ros/t_top/launch/opentera_teleop.launch +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ros/t_top/launch/opentera_teleop.launch.xml b/ros/t_top/launch/opentera_teleop.launch.xml new file mode 100644 index 00000000..1b2d280d --- /dev/null +++ b/ros/t_top/launch/opentera_teleop.launch.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ros/t_top/launch/perceptions.launch b/ros/t_top/launch/perceptions.launch deleted file mode 100644 index 60bc82be..00000000 --- a/ros/t_top/launch/perceptions.launch +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ros/t_top/launch/perceptions.launch.xml b/ros/t_top/launch/perceptions.launch.xml new file mode 100644 index 00000000..a4ab8ea1 --- /dev/null +++ b/ros/t_top/launch/perceptions.launch.xml @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ros/t_top/launch/perceptions/audio_analyzer.launch b/ros/t_top/launch/perceptions/audio_analyzer.launch.xml similarity index 62% rename from ros/t_top/launch/perceptions/audio_analyzer.launch rename to ros/t_top/launch/perceptions/audio_analyzer.launch.xml index 9373095f..d2424648 100644 --- a/ros/t_top/launch/perceptions/audio_analyzer.launch +++ b/ros/t_top/launch/perceptions/audio_analyzer.launch.xml @@ -2,13 +2,13 @@ - + - - + + - - + + diff --git a/ros/t_top/launch/perceptions/ego_noise_reduction.launch b/ros/t_top/launch/perceptions/ego_noise_reduction.launch.xml similarity index 62% rename from ros/t_top/launch/perceptions/ego_noise_reduction.launch rename to ros/t_top/launch/perceptions/ego_noise_reduction.launch.xml index 0d8b39ca..458f9bf6 100644 --- a/ros/t_top/launch/perceptions/ego_noise_reduction.launch +++ b/ros/t_top/launch/perceptions/ego_noise_reduction.launch.xml @@ -1,15 +1,16 @@ - + - + - + + diff --git a/ros/t_top/launch/perceptions/music_beat_detector.launch b/ros/t_top/launch/perceptions/music_beat_detector.launch deleted file mode 100644 index 5643f28f..00000000 --- a/ros/t_top/launch/perceptions/music_beat_detector.launch +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ros/t_top/launch/perceptions/music_beat_detector.launch.xml b/ros/t_top/launch/perceptions/music_beat_detector.launch.xml new file mode 100644 index 00000000..af5a24a4 --- /dev/null +++ b/ros/t_top/launch/perceptions/music_beat_detector.launch.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ros/t_top/launch/perceptions/odas.launch b/ros/t_top/launch/perceptions/odas.launch.xml similarity index 54% rename from ros/t_top/launch/perceptions/odas.launch rename to ros/t_top/launch/perceptions/odas.launch.xml index 326d33d7..2990fde9 100644 --- a/ros/t_top/launch/perceptions/odas.launch +++ b/ros/t_top/launch/perceptions/odas.launch.xml @@ -1,22 +1,24 @@ - + - + - - + + + - - + + + @@ -24,8 +26,8 @@ - - + + diff --git a/ros/t_top/launch/perceptions/person_identification.launch b/ros/t_top/launch/perceptions/person_identification.launch.xml similarity index 73% rename from ros/t_top/launch/perceptions/person_identification.launch rename to ros/t_top/launch/perceptions/person_identification.launch.xml index 3ad5614e..a9042e55 100644 --- a/ros/t_top/launch/perceptions/person_identification.launch +++ b/ros/t_top/launch/perceptions/person_identification.launch.xml @@ -1,8 +1,8 @@ - + - + @@ -11,7 +11,7 @@ - + diff --git a/ros/t_top/launch/perceptions/pose_classifier.launch b/ros/t_top/launch/perceptions/pose_classifier.launch.xml similarity index 55% rename from ros/t_top/launch/perceptions/pose_classifier.launch rename to ros/t_top/launch/perceptions/pose_classifier.launch.xml index 92ab6d24..e9fc77ce 100644 --- a/ros/t_top/launch/perceptions/pose_classifier.launch +++ b/ros/t_top/launch/perceptions/pose_classifier.launch.xml @@ -1,6 +1,6 @@ - - + + diff --git a/ros/t_top/launch/perceptions/robot_name_detector.launch b/ros/t_top/launch/perceptions/robot_name_detector.launch.xml similarity index 81% rename from ros/t_top/launch/perceptions/robot_name_detector.launch rename to ros/t_top/launch/perceptions/robot_name_detector.launch.xml index 6de11080..7c96f92e 100644 --- a/ros/t_top/launch/perceptions/robot_name_detector.launch +++ b/ros/t_top/launch/perceptions/robot_name_detector.launch.xml @@ -1,15 +1,15 @@ - + - + - + diff --git a/ros/t_top/launch/perceptions/rtabmap.launch b/ros/t_top/launch/perceptions/rtabmap.launch deleted file mode 100644 index 07583aa8..00000000 --- a/ros/t_top/launch/perceptions/rtabmap.launch +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ros/t_top/launch/perceptions/rtabmap.launch.xml b/ros/t_top/launch/perceptions/rtabmap.launch.xml new file mode 100644 index 00000000..dabcea11 --- /dev/null +++ b/ros/t_top/launch/perceptions/rtabmap.launch.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ros/t_top/launch/perceptions/speech_to_text.launch b/ros/t_top/launch/perceptions/speech_to_text.launch.xml similarity index 52% rename from ros/t_top/launch/perceptions/speech_to_text.launch rename to ros/t_top/launch/perceptions/speech_to_text.launch.xml index 3acd9fa4..0bd8a431 100644 --- a/ros/t_top/launch/perceptions/speech_to_text.launch +++ b/ros/t_top/launch/perceptions/speech_to_text.launch.xml @@ -2,23 +2,24 @@ - + + + - + - + - - - - + + + diff --git a/ros/t_top/launch/perceptions/vad.launch b/ros/t_top/launch/perceptions/vad.launch deleted file mode 100644 index 69e8aa99..00000000 --- a/ros/t_top/launch/perceptions/vad.launch +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/ros/t_top/launch/perceptions/vad.launch.xml b/ros/t_top/launch/perceptions/vad.launch.xml new file mode 100644 index 00000000..99291914 --- /dev/null +++ b/ros/t_top/launch/perceptions/vad.launch.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/ros/t_top/launch/perceptions/video_analyzer.launch b/ros/t_top/launch/perceptions/video_analyzer.launch.xml similarity index 62% rename from ros/t_top/launch/perceptions/video_analyzer.launch rename to ros/t_top/launch/perceptions/video_analyzer.launch.xml index 17b378cc..e8fa0438 100644 --- a/ros/t_top/launch/perceptions/video_analyzer.launch +++ b/ros/t_top/launch/perceptions/video_analyzer.launch.xml @@ -20,23 +20,23 @@ - - + + - - - - - - - - + + + + + + + + - - + + - + @@ -49,25 +49,25 @@ - + - - - - - - - - + + + + + + + + - - + + - + diff --git a/ros/t_top/launch/platform.launch b/ros/t_top/launch/platform.launch deleted file mode 100644 index 1f97803d..00000000 --- a/ros/t_top/launch/platform.launch +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ros/t_top/launch/platform.launch.xml b/ros/t_top/launch/platform.launch.xml new file mode 100644 index 00000000..bfcb8bf5 --- /dev/null +++ b/ros/t_top/launch/platform.launch.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ros/t_top/launch/platform/actuators.launch b/ros/t_top/launch/platform/actuators.launch.xml similarity index 68% rename from ros/t_top/launch/platform/actuators.launch rename to ros/t_top/launch/platform/actuators.launch.xml index 0e6e84b9..073f9002 100644 --- a/ros/t_top/launch/platform/actuators.launch +++ b/ros/t_top/launch/platform/actuators.launch.xml @@ -3,32 +3,34 @@ - + - + - + + - + - + + diff --git a/ros/t_top/launch/platform/daemon_ros_client.launch b/ros/t_top/launch/platform/daemon_ros_client.launch deleted file mode 100644 index 106cfb21..00000000 --- a/ros/t_top/launch/platform/daemon_ros_client.launch +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - name: led_emotions/set_led_colors - priority: 1 - timeout_s: 0.1 - - name: dance/set_led_colors - priority: 2 - timeout_s: 2.0 - - name: led_animations/set_led_colors - priority: 3 - timeout_s: 0.1 - - name: robot_name_detector/set_led_colors - priority: 4 - timeout_s: 0.2 - - - - - - - - - - name: teleoperation/set_torso_orientation - priority: 1 - timeout_s: 0.5 - - name: gesture/set_torso_orientation - priority: 2 - timeout_s: 0.5 - - name: dance/set_torso_orientation - priority: 3 - timeout_s: 0.5 - - name: explore/set_torso_orientation - priority: 4 - timeout_s: 0.5 - - name: sound_object_person_following/set_torso_orientation - priority: 5 - timeout_s: 0.5 - - name: specific_face_following/set_torso_orientation - priority: 6 - timeout_s: 0.5 - - name: nearest_face_following/set_torso_orientation - priority: 7 - timeout_s: 0.5 - - name: sound_following/set_torso_orientation - priority: 8 - timeout_s: 0.5 - - name: other/set_torso_orientation - priority: 9 - timeout_s: 0.5 - - - - - - - - - - name: teleoperation/set_head_pose - priority: 1 - timeout_s: 0.5 - - name: gesture/set_head_pose - priority: 2 - timeout_s: 0.5 - - name: dance/set_head_pose - priority: 3 - timeout_s: 0.5 - - name: explore/set_head_pose - priority: 4 - timeout_s: 0.5 - - name: sound_object_person_following/set_head_pose - priority: 5 - timeout_s: 0.5 - - name: specific_face_following/set_head_pose - priority: 6 - timeout_s: 0.5 - - name: nearest_face_following/set_head_pose - priority: 7 - timeout_s: 0.5 - - name: sound_following/set_head_pose - priority: 8 - timeout_s: 0.5 - - name: other/set_head_pose - priority: 9 - timeout_s: 0.5 - - [too_close_reaction/set_head_pose] - - - diff --git a/ros/t_top/launch/platform/daemon_ros_client.launch.xml b/ros/t_top/launch/platform/daemon_ros_client.launch.xml new file mode 100644 index 00000000..3be6bc87 --- /dev/null +++ b/ros/t_top/launch/platform/daemon_ros_client.launch.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ros/t_top/launch/platform/realsense.launch b/ros/t_top/launch/platform/realsense.launch deleted file mode 100644 index 856c8f43..00000000 --- a/ros/t_top/launch/platform/realsense.launch +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ros/t_top/launch/platform/sensors.launch b/ros/t_top/launch/platform/sensors.launch deleted file mode 100644 index aac20ef3..00000000 --- a/ros/t_top/launch/platform/sensors.launch +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [front-left, front-right, rear-left, rear-right, front-center, lfe, side-left, side-right, aux0, aux1, aux2, aux3, aux4, aux5, aux6, aux7] - - - diff --git a/ros/t_top/launch/platform/sensors.launch.xml b/ros/t_top/launch/platform/sensors.launch.xml new file mode 100644 index 00000000..c889ea37 --- /dev/null +++ b/ros/t_top/launch/platform/sensors.launch.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ros/t_top/launch/recording.launch b/ros/t_top/launch/recording.launch deleted file mode 100644 index 344c135d..00000000 --- a/ros/t_top/launch/recording.launch +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - name: camera_3d - format: rgb8 - width: 1280 - height: 720 - framerate: 15 - codec: h264 - bitrate: 2000000 - delay_s: 0.35 - - - - name: odas - format: signed_16 - channel_count: 1 - sampling_frequency: 16000 - codec: aac - - - - - - - - - - - - - - name: camera_2d_wide - format: bgr8 - width: 1280 - height: 720 - framerate: 5 - codec: h264 - bitrate: 2000000 - delay_s: 0.0 - - - - name: raw - format: signed_32 - channel_count: 16 - sampling_frequency: 16000 - codec: aac - - - - - - - diff --git a/ros/t_top/launch/recording.launch.xml b/ros/t_top/launch/recording.launch.xml new file mode 100644 index 00000000..1ed8d9d3 --- /dev/null +++ b/ros/t_top/launch/recording.launch.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ros/t_top/launch/rviz.launch b/ros/t_top/launch/rviz.launch deleted file mode 100644 index 3391667c..00000000 --- a/ros/t_top/launch/rviz.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/ros/t_top/launch/tests/test_head_roll_image_rotation_node.launch b/ros/t_top/launch/tests/test_head_roll_image_rotation_node.launch deleted file mode 100644 index c4bbc16f..00000000 --- a/ros/t_top/launch/tests/test_head_roll_image_rotation_node.launch +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/ros/t_top/launch/tests/test_pose_classifier_node.launch b/ros/t_top/launch/tests/test_pose_classifier_node.launch deleted file mode 100644 index 63e04e43..00000000 --- a/ros/t_top/launch/tests/test_pose_classifier_node.launch +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ros/t_top/launch/tests/test_resampling_node.launch b/ros/t_top/launch/tests/test_resampling_node.launch deleted file mode 100644 index 91cf4336..00000000 --- a/ros/t_top/launch/tests/test_resampling_node.launch +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ros/t_top/launch/tests/test_talk.launch b/ros/t_top/launch/tests/test_talk.launch deleted file mode 100644 index a77555b7..00000000 --- a/ros/t_top/launch/tests/test_talk.launch +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ros/t_top/launch/tests/test_video_analyzer_3d_node.launch b/ros/t_top/launch/tests/test_video_analyzer_3d_node.launch deleted file mode 100644 index d89d1c13..00000000 --- a/ros/t_top/launch/tests/test_video_analyzer_3d_node.launch +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ros/t_top/launch/tests/test_whisper_speech_to_text.launch b/ros/t_top/launch/tests/test_whisper_speech_to_text.launch deleted file mode 100644 index cc6d1679..00000000 --- a/ros/t_top/launch/tests/test_whisper_speech_to_text.launch +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ros/t_top/meshes/d435.dae b/ros/t_top/meshes/d435.dae deleted file mode 100644 index 41f3a87c..00000000 --- a/ros/t_top/meshes/d435.dae +++ /dev/null @@ -1,1658 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - realsense-ros/d435.dae at development · IntelRealSense/realsense-ros - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Skip to content - - - - - - - - - -
- -
- - - - - -
- - - -
- - - - - - - - - -
-
-
- - - - - - - - - - - - - -
- -
- -
-

- - - / - - realsense-ros - - -

- - -
- -
    - -
  • - -
    - - - - - - - - Watch - - - - - -
    -
    -

    Notifications

    - -
    - -
    -
    - - - - - - - - -
    - -
    -
    -
    - - -
    -
    - -
    - - - -
  • - -
  • -
    -
    - - -
    -
    - - -
    - -
  • - -
  • -
    -
    - - - Fork - - - -
    - -

    Fork realsense-ros

    -
    - -
    - -
    -

    If this dialog fails to load, you can visit the fork page directly.

    -
    -
    - -
    -
    -
    - - -
  • -
- -
- - - - -
- - -
-
- - - - -
- - - - Permalink - - - -
- -
-
- - - development - - - - -
-
-
- Switch branches/tags - -
- - - -
- -
- -
- - -
- -
- - - - - - - - - - - - - - - - -
- - -
-
-
-
- -
- -
- - - - Go to file - - -
- - - - - - - - - -
-
-
- - - -
- -
-
- - - -
- - - - - - -
-
- - Latest commit - 52543ac - Mar 20, 2019 - - - - - - History - - -
-
- -
- -
-
- - - 0 - - contributors - - -
- -

- Users who have contributed to this file -

-
- - - - - - -
-
-
-
- - - - - - - - - - - - - -
- -
- - -
- - 15.1 MB -
- -
- - - -
- - - - -
- -
-
- -
- -
-
- - - -
-
- View raw -

(Sorry about that, but we can’t show files that are this big right now.)

-
-
- -
- - - - -
- - -
- - -
-
- - -
- - - -
-
- -
-
- -
- - - - - - - - - - - - - - - - - - - - diff --git a/ros/t_top/meshes/rotating_base_mesh.dae b/ros/t_top/meshes/rotating_base_mesh.dae deleted file mode 100644 index 192230c7..00000000 --- a/ros/t_top/meshes/rotating_base_mesh.dae +++ /dev/null @@ -1,107 +0,0 @@ - - - - - Blender User - Blender 2.92.0 commit date:2021-02-24, commit time:16:25, hash:02948a2cab44 - - 2021-05-28T09:28:17 - 2021-05-28T09:28:17 - - Z_UP - - - - - - 1000 1000 1000 - 1 - 0 - 0.00111109 - - - - - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - 0 - 1000 - 29.99998 - 75 - 0.15 - 0 - 1 - 2 - 0.04999995 - 30.002 - 1 - 3 - 2880 - 3 - 1 - 1 - 0.1 - 0.1 - 1 - - - - - - - - - - 0.1840202 0.02449995 0.02403783 0.168258 0.02449995 0.01373994 0.1737391 0.02449995 0.07950961 0.009601831 0.02449995 0.06820672 0.003488302 0.02449995 0.08601462 0.02108168 0.02449995 0.07950961 0.1655865 0.02449995 0.03138881 0.1361417 0.02449995 0.04838883 0.1408208 0.02449995 0.07950961 0.209437 0.02449995 0.1763521 0.2183982 0.02449995 0.1597933 0.18825 0.02449995 0.1659808 0.1978725 0.02449995 0.1912101 0.18825 0.02449995 0.1999807 0.1840202 0.02449995 0.203962 0.1737391 0.02449995 0.1999807 0.168258 0.02449995 0.21426 0.1510156 0.02449995 0.2218232 0.15975 0.02449995 0.1999807 0.1327638 0.02449995 0.2264451 0.1737391 0.02449995 0.1659808 0.1737391 0.02449995 0.1591464 0.15975 0.02449995 0.1659808 0.1408208 0.02449995 0.1591464 0.05426079 0.02449995 0.1591464 0.05426079 0.02449995 0.1659808 0.06825 0.02449995 0.1659808 0.114 0.02449995 0.1591464 0.06825 0.02449995 0.1999807 0.09523618 0.02449995 0.2264451 0.03974992 0.02449995 0.1999807 0.0439797 0.02449995 0.203962 0.05426079 0.02449995 0.1999807 0.05974197 0.02449995 0.21426 0.07698422 0.02449995 0.2218232 0.03974992 0.02449995 0.1659808 0.02108168 0.02449995 0.1591464 0.114 0.02449995 0.07950961 0.1513365 0.02449995 0.006707191 0.1510156 0.02449995 0.006176829 0.1218916 0.02449995 0.02370721 0.1327638 0.02449995 0.001554787 0.114 0.02449995 0.003353536 0.114 0.02449995 0 0.09523618 0.02449995 0.001554787 0.05426079 0.02449995 0.07950961 0.01666343 0.02449995 0.1106303 0.0461083 0.02449995 0.1276302 0.03185832 0.02449995 0.152312 0.003488302 0.02449995 0.1419852 0.009601831 0.02449995 0.1597933 0.01856297 0.02449995 0.1763521 0.03012746 0.02449995 0.1912101 0.002413392 0.02449995 0.135312 3.89367e-4 0.02449995 0.104586 3.89367e-4 0.02449995 0.123414 0.06241345 0.02449995 0.03138881 0.09185832 0.02449995 0.04838883 0.1061083 0.02449995 0.02370721 0.07666343 0.02449995 0.006707191 0.05974197 0.02449995 0.01373994 0.0439797 0.02449995 0.02403783 0.03012746 0.02449995 0.03678989 0.01856297 0.02449995 0.0516479 0.07698422 0.02449995 0.006176829 0.2183982 0.02449995 0.06820672 0.209437 0.02449995 0.0516479 0.1978725 0.02449995 0.03678989 0.1818916 0.02449995 0.1276302 0.2113365 0.02449995 0.1106303 0.2245116 0.02449995 0.08601462 0.1961417 0.02449995 0.152312 0.2245116 0.02449995 0.1419852 0.2255865 0.02449995 0.135312 0.2276106 0.02449995 0.123414 0.2276106 0.02449995 0.104586 0.114 0.02449995 0.228 0.114 0 0 0.1327638 0 0.001554787 0.1510156 0 0.006176829 0.168258 0 0.01373994 0.1840202 0 0.02403783 0.1978725 0 0.03678989 0.209437 0 0.0516479 0.2183982 0 0.06820672 0.2245116 0 0.08601462 0.2276106 0 0.104586 0.2276106 0 0.123414 0.2245116 0 0.1419852 0.2183982 0 0.1597933 0.209437 0 0.1763521 0.1978725 0 0.1912101 0.1840202 0 0.203962 0.168258 0 0.21426 0.1510156 0 0.2218232 0.1327638 0 0.2264451 0.114 0 0.228 0.09523618 0 0.2264451 0.07698422 0 0.2218232 0.05974197 0 0.21426 0.0439797 0 0.203962 0.03012746 0 0.1912101 0.01856297 0 0.1763521 0.009601831 0 0.1597933 0.003488302 0 0.1419852 3.89367e-4 0 0.123414 3.89367e-4 0 0.104586 0.003488302 0 0.08601462 0.009601831 0 0.06820672 0.01856297 0 0.0516479 0.03012746 0 0.03678989 0.0439797 0 0.02403783 0.05974197 0 0.01373994 0.07698422 0 0.006176829 0.09523618 0 0.001554787 0.114 0 0.114 0.07666343 0.07099997 0.006707191 0.1061083 0.07099997 0.02370721 0.06241345 0.07099997 0.03138881 0.09185832 0.07099997 0.04838883 0.03185832 0.07099997 0.152312 0.002413392 0.07099997 0.135312 0.0461083 0.07099997 0.1276302 0.01666343 0.07099997 0.1106303 0.1218916 0.07099997 0.02370721 0.1513365 0.07099997 0.006707191 0.1361417 0.07099997 0.04838883 0.1655865 0.07099997 0.03138881 0.1818916 0.07099997 0.1276302 0.2113365 0.07099997 0.1106303 0.1961417 0.07099997 0.152312 0.2255865 0.07099997 0.135312 0.03974992 0.07099997 0.1999807 0.03974992 0.07099997 0.1659808 0.06825 0.07099997 0.1999807 0.06825 0.07099997 0.1659808 0.15975 0.07099997 0.1999807 0.15975 0.07099997 0.1659808 0.18825 0.07099997 0.1999807 0.18825 0.07099997 0.1659808 - - - - - - - - - - 0 1 0 0 1 0 0 1 0 0 1 -2.62332e-7 0 1 0 0 1 -1.20042e-5 0 1 1.00754e-6 0 1 -1.72591e-7 0 1 1.90497e-7 0 1 0 0 1 3.45181e-7 0 1 1.87431e-7 0 1 0 0 1 0 0 1 5.52462e-6 0 1 -1.28049e-7 0 1 -1.46949e-7 0 1 -2.67768e-7 0 1 -2.74532e-7 0 1 1.40114e-6 0 1 5.13386e-7 0 1 -5.13386e-7 0 1 -1.25237e-7 0 1 0 0 1 0 0 1 0 0 1 0 0 1 1.24522e-7 0 1 7.10076e-6 0 1 -8.66386e-6 0 1 0 0 1 0 0 1 0 0 1 1.51147e-7 0 1 -3.9352e-7 0 1 3.64127e-7 0 1 -1.31667e-7 0 1 1.42892e-7 0 1 -1.36015e-7 0 1 0 0 1 0 0.082578 0 -0.9965847 0.2454885 0 -0.9693995 0.4016907 0 -0.9157755 0.4016906 0 -0.9157755 0.5469476 0 -0.837167 0.6772834 0 -0.7357224 0.6772835 0 -0.7357223 0.7891396 0 -0.614214 0.7891395 0 -0.6142141 0.8794734 0 -0.4759481 0.9458181 0 -0.324697 0.9863616 0 -0.1645936 1 0 0 0.9863613 0 0.1645949 0.9863613 0 0.1645951 0.945819 0 0.3246944 0.9458192 0 0.3246938 0.8794732 0 0.4759485 0.7891395 0 0.6142141 0.6772812 0 0.7357244 0.67728 0 0.7357254 0.5469486 0 0.8371662 0.5469501 0 0.8371652 0.4016942 0 0.9157739 0.2454823 0 0.9694012 0.0825836 0 0.9965842 0.08258563 0 0.9965841 -0.08258551 0 0.9965841 -0.08258348 0 0.9965842 -0.2454801 0 0.9694017 -0.4016972 0 0.9157726 -0.5469486 0 0.8371663 -0.5469473 0 0.8371672 -0.6772816 0 0.735724 -0.6772827 0 0.7357229 -0.7891396 0 0.614214 -0.8794745 0 0.475946 -0.9458173 0 0.3246994 -0.9458171 0 0.3247 -0.9863618 0 0.164592 -0.9863618 0 0.1645918 -1 0 0 -0.986362 0 -0.1645905 -0.9458162 0 -0.3247027 -0.8794748 0 -0.4759457 -0.7891396 0 -0.614214 -0.7891396 0 -0.6142138 -0.677285 0 -0.7357208 -0.6772848 0 -0.7357209 -0.5469462 0 -0.8371679 -0.4016937 0 -0.9157742 -0.4016937 0 -0.9157742 -0.2454863 0 -0.9694002 -0.08257782 0 -0.9965847 0 -1 0 0.5000004 0 -0.8660253 -0.8660254 0 -0.5000001 -0.8660255 0 -0.5 -0.5000004 0 0.8660252 -0.5000004 0 0.8660253 0.8660254 0 0.5000002 0.8660254 0 0.5000001 -0.4999986 0 0.8660263 -0.4999991 0 0.8660261 0.8660264 0 0.4999984 0.8660263 0 0.4999987 0.499998 0 -0.8660266 0.4999976 0 -0.8660268 -0.8660248 0 -0.5000011 -0.8660246 0 -0.5000014 0 1 -2.40279e-7 -0.4999999 0 -0.8660256 -0.5 0 -0.8660255 -0.8660236 0 0.5000033 -0.8660236 0 0.5000032 0.5000013 0 0.8660248 0.5000014 0 0.8660247 0.8660251 0 -0.5000005 0.8660252 0 -0.5000005 -0.4999971 0 -0.8660271 -0.4999976 0 -0.8660268 -0.8660244 0 0.5000019 -0.8660247 0 0.5000015 0.5000007 0 0.866025 0.5000003 0 0.8660253 0.8660253 0 -0.5000003 0.8660255 0 -0.4999999 0 0 1 0 0 -1 - - - - - - - - - - - - - - -

0 0 1 0 2 0 3 1 4 1 5 1 6 2 7 2 8 2 9 3 10 3 11 3 9 4 11 4 12 4 12 1 11 1 13 1 12 5 13 5 14 5 14 6 13 6 15 6 14 7 15 7 16 7 16 1 15 1 17 1 17 8 15 8 18 8 17 1 18 1 19 1 20 1 21 1 22 1 22 1 21 1 23 1 24 1 25 1 26 1 24 1 26 1 27 1 27 1 26 1 28 1 27 9 28 9 29 9 30 1 31 1 32 1 32 10 31 10 33 10 32 1 33 1 28 1 28 11 33 11 34 11 28 1 34 1 29 1 30 1 35 1 36 1 8 1 7 1 37 1 8 12 2 12 6 12 6 13 2 13 1 13 6 1 1 1 38 1 38 1 1 1 39 1 38 14 39 14 40 14 40 15 39 15 41 15 40 16 41 16 42 16 42 1 41 1 43 1 42 1 43 1 44 1 45 17 5 17 46 17 47 1 48 1 24 1 49 1 50 1 36 1 36 1 50 1 51 1 36 18 51 18 30 18 30 19 51 19 52 19 30 1 52 1 31 1 46 1 5 1 53 1 53 1 5 1 4 1 53 1 4 1 54 1 54 1 55 1 53 1 53 1 55 1 49 1 53 1 49 1 48 1 48 1 49 1 36 1 48 20 36 20 24 20 24 21 36 21 35 21 24 1 35 1 25 1 56 1 45 1 57 1 57 22 45 22 37 22 57 23 37 23 58 23 59 24 60 24 56 24 56 1 60 1 61 1 56 1 61 1 45 1 45 1 61 1 62 1 45 25 62 25 5 25 5 1 62 1 63 1 5 1 63 1 3 1 7 26 40 26 37 26 37 1 40 1 42 1 37 1 42 1 58 1 58 1 42 1 44 1 58 27 44 27 59 27 59 28 44 28 64 28 59 29 64 29 60 29 65 1 66 1 2 1 2 30 66 30 67 30 2 31 67 31 0 31 2 32 68 32 65 32 65 1 68 1 69 1 65 33 69 33 70 33 20 1 11 1 21 1 21 34 11 34 10 34 21 35 10 35 71 35 71 36 10 36 72 36 71 37 72 37 73 37 73 1 72 1 74 1 73 1 74 1 69 1 69 1 74 1 75 1 69 38 75 38 70 38 29 1 76 1 27 1 27 1 76 1 19 1 27 39 19 39 23 39 23 1 19 1 18 1 23 1 18 1 22 1 71 1 68 1 21 1 21 1 68 1 2 1 21 1 2 1 23 1 23 1 2 1 8 1 23 1 8 1 27 1 27 1 8 1 37 1 27 1 37 1 24 1 24 1 37 1 45 1 24 1 45 1 47 1 47 40 45 40 46 40 77 41 41 41 78 41 78 42 41 42 39 42 78 42 39 42 79 42 79 43 39 43 1 43 79 44 1 44 80 44 80 45 1 45 0 45 80 45 0 45 81 45 81 46 0 46 67 46 81 47 67 47 82 47 82 48 67 48 66 48 82 49 66 49 83 49 83 50 66 50 65 50 83 50 65 50 84 50 84 51 65 51 70 51 84 51 70 51 85 51 85 52 70 52 75 52 85 52 75 52 86 52 86 53 75 53 74 53 86 53 74 53 87 53 87 54 74 54 72 54 87 55 72 55 88 55 88 56 72 56 10 56 88 57 10 57 89 57 89 58 10 58 9 58 89 58 9 58 90 58 90 59 9 59 12 59 90 59 12 59 91 59 91 60 12 60 14 60 91 61 14 61 92 61 92 62 14 62 16 62 92 63 16 63 93 63 93 64 16 64 17 64 93 64 17 64 94 64 94 65 17 65 19 65 94 65 19 65 95 65 95 66 19 66 76 66 95 67 76 67 96 67 96 68 76 68 29 68 96 69 29 69 97 69 97 70 29 70 34 70 97 70 34 70 98 70 98 71 34 71 33 71 98 71 33 71 99 71 99 72 33 72 31 72 99 73 31 73 100 73 100 74 31 74 52 74 100 75 52 75 101 75 101 76 52 76 51 76 101 76 51 76 102 76 102 77 51 77 50 77 102 77 50 77 103 77 103 78 50 78 49 78 103 79 49 79 104 79 104 80 49 80 55 80 104 81 55 81 105 81 105 82 55 82 54 82 105 82 54 82 106 82 106 83 54 83 4 83 106 83 4 83 107 83 107 84 4 84 3 84 107 84 3 84 108 84 108 85 3 85 63 85 108 85 63 85 109 85 109 86 63 86 62 86 109 87 62 87 110 87 110 88 62 88 61 88 110 89 61 89 111 89 111 90 61 90 60 90 111 90 60 90 112 90 112 91 60 91 64 91 112 92 64 92 113 92 113 93 64 93 44 93 113 93 44 93 114 93 114 94 44 94 43 94 114 94 43 94 77 94 77 41 43 41 41 41 96 95 97 95 115 95 96 95 115 95 95 95 92 95 93 95 115 95 115 95 93 95 94 95 115 95 94 95 95 95 89 95 90 95 115 95 115 95 90 95 91 95 115 95 91 95 92 95 86 95 87 95 115 95 115 95 87 95 88 95 115 95 88 95 89 95 83 95 84 95 115 95 115 95 84 95 85 95 115 95 85 95 86 95 80 95 81 95 115 95 115 95 81 95 82 95 115 95 82 95 83 95 77 95 78 95 115 95 115 95 78 95 79 95 115 95 79 95 80 95 112 95 113 95 115 95 115 95 113 95 114 95 115 95 114 95 77 95 109 95 110 95 115 95 115 95 110 95 111 95 115 95 111 95 112 95 106 95 107 95 115 95 115 95 107 95 108 95 115 95 108 95 109 95 103 95 104 95 115 95 115 95 104 95 105 95 115 95 105 95 106 95 100 95 101 95 115 95 115 95 101 95 102 95 115 95 102 95 103 95 97 95 98 95 115 95 115 95 98 95 99 95 115 95 99 95 100 95 116 96 117 96 59 96 59 96 117 96 58 96 118 97 116 97 56 97 56 98 116 98 59 98 119 99 118 99 57 99 57 100 118 100 56 100 117 101 119 101 58 101 58 102 119 102 57 102 118 1 119 1 116 1 116 1 119 1 117 1 120 103 121 103 48 103 48 104 121 104 53 104 122 105 120 105 47 105 47 106 120 106 48 106 123 107 122 107 46 107 46 108 122 108 47 108 121 109 123 109 53 109 53 110 123 110 46 110 122 111 123 111 120 111 120 1 123 1 121 1 124 112 125 112 40 112 40 113 125 113 38 113 126 114 124 114 7 114 7 115 124 115 40 115 127 116 126 116 6 116 6 117 126 117 7 117 125 118 127 118 38 118 38 119 127 119 6 119 126 1 127 1 124 1 124 1 127 1 125 1 128 120 129 120 68 120 68 121 129 121 69 121 130 122 128 122 71 122 71 123 128 123 68 123 131 124 130 124 73 124 73 125 130 125 71 125 129 126 131 126 69 126 69 127 131 127 73 127 130 1 131 1 128 1 128 1 131 1 129 1 132 82 133 82 30 82 30 82 133 82 35 82 28 128 134 128 32 128 32 128 134 128 132 128 32 128 132 128 30 128 135 53 134 53 26 53 26 53 134 53 28 53 35 129 133 129 25 129 25 129 133 129 135 129 25 129 135 129 26 129 134 1 135 1 132 1 132 1 135 1 133 1 136 82 137 82 18 82 18 82 137 82 22 82 13 128 138 128 15 128 15 128 138 128 136 128 15 128 136 128 18 128 139 53 138 53 11 53 11 53 138 53 13 53 22 129 137 129 20 129 20 129 137 129 139 129 20 129 139 129 11 129 138 1 139 1 136 1 136 1 139 1 137 1

-
-
-
-
- - - - 0.8660254 2.18557e-8 0.5 -0.161191 0.5 -3.78552e-8 -0.8660254 0.043191 0 1 -4.37114e-8 -0.059637 0 0 0 1 - - - - -0.2908646 -0.7711008 0.5663932 4.076245 0.9551712 -0.1998834 0.2183911 1.005454 -0.05518897 0.6045246 0.7946723 5.903862 0 0 0 1 - - - - - - - -
\ No newline at end of file diff --git a/ros/t_top/meshes/stewart_platform_mesh.dae b/ros/t_top/meshes/stewart_platform_mesh.dae deleted file mode 100644 index 776fdfd5..00000000 --- a/ros/t_top/meshes/stewart_platform_mesh.dae +++ /dev/null @@ -1,59 +0,0 @@ - - - - - Blender User - Blender 2.92.0 commit date:2021-02-24, commit time:16:25, hash:02948a2cab44 - - 2021-05-28T09:30:07 - 2021-05-28T09:30:07 - - Z_UP - - - - - - - 0.1379659 0.05324774 0.135 0.139773 0.06436735 0.135 0.1264669 0.06999999 0.135 0.14 0.06999999 0.135 0.139773 0.07563263 0.135 0.02150923 0.01951581 0.135 0.03023535 0.01239109 0.135 0.04176652 0.02109807 0.135 0.03999137 0.006758451 0.135 0.08400177 0.001414597 0.135 0.09482234 0.004548788 0.135 0.09823346 0.02109807 0.135 0.105 0.009378194 0.135 0.1142712 0.01577752 0.135 0.05052477 0.1372362 0.135 0.03999137 0.1332415 0.135 0.04176652 0.1189017 0.135 0.03023535 0.1276088 0.135 0.003602445 0.09216672 0.135 9.06482e-4 0.08122879 0.135 0.01353293 0.06999999 0.135 0 0.06999999 0.135 9.06482e-4 0.05877119 0.135 0.1223958 0.1164186 0.135 0.1142712 0.1242223 0.135 0.09823346 0.1189017 0.135 0.105 0.1306217 0.135 0.09482234 0.1354511 0.135 0.05052477 0.002763569 0.135 0.06156229 5.1038e-4 0.135 0.07281857 5.67734e-5 0.135 0.08400177 0.1385853 0.135 0.07281857 0.1399432 0.135 0.06156229 0.1394896 0.135 0.1223958 0.02358138 0.135 0.1291633 0.03258723 0.135 0.1343985 0.0425623 0.135 0.1379659 0.08675205 0.135 0.1343985 0.09743762 0.135 0.1291633 0.1074126 0.135 0.003602445 0.0478332 0.135 0.008018076 0.0374692 0.135 0.01403898 0.02794802 0.135 0.02150923 0.1204842 0.135 0.01403898 0.112052 0.135 0.008018076 0.1025305 0.135 0.03023535 0.1276088 0.125 0.03999137 0.1332415 0.125 0.04277521 0.1171547 0.125 0.02150923 0.1204842 0.125 0.03999137 0.006758451 0.125 0.03023535 0.01239109 0.125 0.04277521 0.02284514 0.125 0.1379659 0.08675205 0.125 0.139773 0.07563263 0.125 0.1244496 0.06999999 0.125 0.14 0.06999999 0.125 0.139773 0.06436735 0.125 0.003602445 0.0478332 0.125 9.06482e-4 0.05877119 0.125 0.01555043 0.06999999 0.125 0 0.06999999 0.125 9.06482e-4 0.08122879 0.125 0.05052477 0.002763569 0.125 0.02150923 0.01951581 0.125 0.01403898 0.02794802 0.125 0.008018076 0.0374692 0.125 0.1223958 0.02358138 0.125 0.1142712 0.01577752 0.125 0.09722477 0.02284514 0.125 0.105 0.009378194 0.125 0.09482234 0.004548788 0.125 0.08400177 0.1385853 0.125 0.09482234 0.1354511 0.125 0.09722477 0.1171547 0.125 0.105 0.1306217 0.125 0.1142712 0.1242223 0.125 0.003602445 0.09216672 0.125 0.008018076 0.1025305 0.125 0.01403898 0.112052 0.125 0.08400177 0.001414597 0.125 0.07281857 5.67734e-5 0.125 0.06156229 5.1038e-4 0.125 0.05052477 0.1372362 0.125 0.06156229 0.1394896 0.125 0.07281857 0.1399432 0.125 0.1223958 0.1164186 0.125 0.1291633 0.1074126 0.125 0.1343985 0.09743762 0.125 0.1379659 0.05324774 0.125 0.1343985 0.0425623 0.125 0.1291633 0.03258723 0.125 0.00999999 0.1345676 0 0.00999999 0.1345676 0.1899999 0.00999999 0.1645676 0 0.00999999 0.1645676 0.1899999 0.1299999 0.1345676 0 0.1299999 0.1645676 0 0.1299999 0.1345676 0.1899999 0.1299999 0.1645676 0.1899999 - - - - - - - - - - 1.47234e-6 0 1 0 0 1 -7.76636e-7 0 1 2.7655e-6 0 1 -7.66094e-7 0 1 -1.47233e-6 0 1 -7.76629e-7 0 1 6.91376e-7 0 1 2.94469e-6 0 1 -3.82455e-6 0 1 8.78829e-7 0 1 -1.44939e-7 0 1 2.76549e-6 0 1 -7.24696e-7 0 1 -7.83897e-7 0 1 1.91229e-6 0 1 -3.45687e-7 0 1 -2.54969e-6 0 1 -2.31903e-6 0 1 3.91922e-7 0 1 1.04522e-6 0 1 1.84045e-7 0 1 -8.01116e-7 0 1 2.81227e-6 0 1 -2.31905e-6 0 1 0 0 -1 -1.34878e-6 0 -1 -1.74026e-6 0 -1 -1.31271e-7 0 -1 -3.89435e-7 0 -1 1.7104e-6 0 -1 0.9991888 0.04026979 0 0.9991889 -0.04026985 0 0.9991888 -0.04026967 0 0.9870505 -0.16041 0 0.9870505 -0.1604107 0 0.9485357 -0.3166704 0 0.9485347 -0.3166736 0 0.8854589 -0.4647179 0 0.8854597 -0.4647163 0 0.7994419 -0.6007435 0 0.7994431 -0.6007418 0 0.6927264 -0.7212005 0 0.6927243 -0.7212025 0 0.5680617 -0.822986 0 0.5680611 -0.8229865 0 0.4286963 -0.9034488 0 0.428695 -0.9034493 0 0.2782156 -0.9605187 0 0.2782149 -0.9605189 0 0.1205314 -0.9927095 0 0.120531 -0.9927096 0 -0.04026561 -0.999189 0 -0.04026556 -0.999189 0 -0.2000178 -0.9797924 0 -0.2000179 -0.9797923 0 -0.3546101 -0.9350143 0 -0.3546083 -0.935015 0 -0.5000004 -0.8660253 0 -0.4999983 -0.8660264 0 -0.6324473 -0.7746036 0 -0.6324458 -0.7746047 0 -0.7485135 -0.6631196 0 -0.7485116 -0.6631218 0 -0.8451891 -0.5344676 0 -0.8451884 -0.5344686 0 -0.9199808 -0.3919636 0 -0.9199801 -0.391965 0 -0.9709421 -0.2393145 0 -0.970942 -0.239315 0 -0.9967574 -0.08046644 0 -0.9967574 -0.08046662 0 -0.9967574 0.08046644 0 -0.9967574 0.08046662 0 -0.9709419 0.239316 0 -0.9709417 0.2393164 0 -0.9199783 0.3919696 0 -0.8451954 0.5344574 0 -0.8451949 0.5344582 0 -0.7485125 0.6631208 0 -0.7485117 0.6631217 0 -0.6324408 0.7746087 0 -0.6324398 0.7746096 0 -0.5000038 0.8660233 0 -0.5000035 0.8660236 0 -0.3546001 0.9350181 0 -0.3545992 0.9350184 0 -0.2000308 0.9797896 0 -0.2000306 0.9797897 0 -0.04026436 0.9991891 0 -0.04026418 0.9991891 0 0.1205378 0.9927088 0 0.1205376 0.9927089 0 0.2782159 0.9605185 0 0.2782146 0.960519 0 0.4286966 0.9034485 0 0.4286946 0.9034495 0 0.5680624 0.8229855 0 0.5680617 0.822986 0 0.6927211 0.7212056 0 0.69272 0.7212067 0 0.7994476 0.6007359 0 0.7994441 0.6007405 0 0.8854593 0.4647172 0 0.885458 0.4647196 0 0.9485356 0.3166704 0 0.9485359 0.3166698 0 0.9870502 0.160412 0 0.9870501 0.1604123 0 0.9991889 0.04026985 0 0 -0.9850808 0.1720932 0 -0.9850807 0.1720935 0.8531019 -0.4925401 0.1721089 0.8531043 -0.49254 0.1720976 -0.8531035 -0.4925418 0.1720961 -0.8531048 -0.4925389 0.1720978 0.8531038 0.4925394 0.1721017 0.8531028 0.4925391 0.1721079 -0.8531032 0.4925402 0.172102 -0.8531053 0.4925386 0.172096 0 0.9850795 0.1721003 0 0.9850795 0.1721005 -1 0 0 1 0 0 0 -1 0 0 1 0 - - - - - - - - - - - - - - -

0 0 1 0 2 0 2 1 1 1 3 1 2 1 3 1 4 1 5 1 6 1 7 1 7 2 6 2 8 2 9 3 10 3 11 3 11 1 10 1 12 1 11 4 12 4 13 4 14 5 15 5 16 5 16 6 15 6 17 6 18 1 19 1 20 1 20 1 19 1 21 1 20 1 21 1 22 1 23 7 24 7 25 7 25 1 24 1 26 1 25 1 26 1 27 1 8 8 28 8 7 8 7 9 28 9 29 9 7 1 29 1 11 1 11 10 29 10 30 10 11 11 30 11 9 11 27 12 31 12 25 12 25 13 31 13 32 13 25 1 32 1 16 1 16 14 32 14 33 14 16 15 33 15 14 15 13 16 34 16 11 16 11 1 34 1 35 1 11 1 35 1 2 1 2 1 35 1 36 1 2 17 36 17 0 17 4 1 37 1 2 1 2 1 37 1 38 1 2 1 38 1 25 1 25 1 38 1 39 1 25 1 39 1 23 1 22 1 40 1 20 1 20 18 40 18 41 18 20 19 41 19 7 19 7 20 41 20 42 20 7 1 42 1 5 1 17 21 43 21 16 21 16 1 43 1 44 1 16 22 44 22 20 22 20 23 44 23 45 23 20 24 45 24 18 24 46 25 47 25 48 25 46 25 48 25 49 25 50 26 51 26 52 26 53 25 54 25 55 25 55 25 54 25 56 25 55 25 56 25 57 25 58 25 59 25 60 25 60 25 59 25 61 25 60 25 61 25 62 25 50 25 52 25 63 25 51 25 64 25 52 25 52 25 64 25 65 25 52 25 65 25 60 25 60 27 65 27 66 27 60 25 66 25 58 25 67 25 68 25 69 25 69 25 68 25 70 25 69 25 70 25 71 25 72 25 73 25 74 25 74 25 73 25 75 25 74 25 75 25 76 25 62 25 77 25 60 25 60 25 77 25 78 25 60 25 78 25 48 25 48 25 78 25 79 25 48 25 79 25 49 25 71 25 80 25 69 25 69 28 80 28 81 28 69 25 81 25 52 25 52 29 81 29 82 29 52 30 82 30 63 30 47 25 83 25 48 25 48 25 83 25 84 25 48 25 84 25 74 25 74 25 84 25 85 25 74 25 85 25 72 25 76 25 86 25 74 25 74 25 86 25 87 25 74 25 87 25 55 25 55 25 87 25 88 25 55 25 88 25 53 25 57 25 89 25 55 25 55 25 89 25 90 25 55 25 90 25 69 25 69 25 90 25 91 25 69 25 91 25 67 25 4 31 3 31 56 31 56 32 3 32 57 32 3 33 1 33 57 33 57 34 1 34 0 34 57 35 0 35 89 35 89 36 0 36 36 36 89 37 36 37 90 37 90 38 36 38 35 38 90 39 35 39 91 39 91 40 35 40 34 40 91 41 34 41 67 41 67 42 34 42 13 42 67 43 13 43 68 43 68 44 13 44 12 44 68 45 12 45 70 45 70 46 12 46 10 46 70 47 10 47 71 47 71 48 10 48 9 48 71 49 9 49 80 49 80 50 9 50 30 50 80 51 30 51 81 51 81 52 30 52 29 52 81 53 29 53 82 53 82 54 29 54 28 54 82 55 28 55 63 55 63 56 28 56 8 56 63 57 8 57 50 57 50 58 8 58 6 58 50 59 6 59 51 59 51 60 6 60 5 60 51 61 5 61 64 61 64 62 5 62 42 62 64 63 42 63 65 63 65 64 42 64 41 64 65 65 41 65 66 65 66 66 41 66 40 66 66 67 40 67 58 67 58 68 40 68 22 68 58 69 22 69 59 69 59 70 22 70 21 70 59 71 21 71 61 71 61 72 21 72 19 72 61 73 19 73 62 73 62 74 19 74 18 74 62 75 18 75 77 75 77 76 18 76 45 76 77 76 45 76 78 76 78 77 45 77 44 77 78 78 44 78 79 78 79 79 44 79 43 79 79 80 43 80 49 80 49 81 43 81 17 81 49 82 17 82 46 82 46 83 17 83 15 83 46 84 15 84 47 84 47 85 15 85 14 85 47 86 14 86 83 86 83 87 14 87 33 87 83 88 33 88 84 88 84 89 33 89 32 89 84 90 32 90 85 90 85 91 32 91 31 91 85 92 31 92 72 92 72 93 31 93 27 93 72 94 27 94 73 94 73 95 27 95 26 95 73 96 26 96 75 96 75 97 26 97 24 97 75 98 24 98 76 98 76 99 24 99 23 99 76 100 23 100 86 100 86 101 23 101 39 101 86 102 39 102 87 102 87 103 39 103 38 103 87 104 38 104 88 104 88 105 38 105 37 105 88 106 37 106 53 106 53 107 37 107 4 107 53 108 4 108 54 108 54 109 4 109 56 109 16 110 48 110 25 110 25 111 48 111 74 111 20 112 60 112 16 112 16 113 60 113 48 113 55 114 2 114 74 114 74 115 2 115 25 115 7 116 52 116 20 116 20 117 52 117 60 117 69 118 11 118 55 118 55 119 11 119 2 119 11 120 69 120 7 120 7 121 69 121 52 121 92 122 93 122 94 122 94 122 93 122 95 122 96 25 92 25 97 25 97 25 92 25 94 25 98 123 96 123 99 123 99 123 96 123 97 123 93 1 98 1 95 1 95 1 98 1 99 1 96 124 98 124 92 124 92 124 98 124 93 124 99 125 97 125 95 125 95 125 97 125 94 125

-
-
-
-
- - - - -4.37114e-8 1 -1.50996e-7 -0.07 1 4.37114e-8 -6.60024e-15 -0.07 0 -1.50996e-7 -1 0.130416 0 0 0 1 - - - - - - - -
\ No newline at end of file diff --git a/ros/t_top/package.xml b/ros/t_top/package.xml index 94f74847..8f7c90b4 100644 --- a/ros/t_top/package.xml +++ b/ros/t_top/package.xml @@ -1,84 +1,29 @@ - + + t_top 0.0.0 The t_top package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rclpy + daemon_ros_client + std_msgs + geometry_msgs + cv_bridge + tf_transformations + hbba_lite - - - - TODO + rosidl_default_runtime + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - geometry_msgs - nav_msgs - rospy - sensor_msgs - std_msgs - tf - hbba_lite - daemon_ros_client - geometry_msgs - nav_msgs - rospy - sensor_msgs - std_msgs - tf - hbba_lite - daemon_ros_client - geometry_msgs - nav_msgs - rospy - sensor_msgs - std_msgs - opentera_webrtc_ros_msgs - tf - hbba_lite - daemon_ros_client - - - - - + ament_cmake diff --git a/ros/t_top/rviz/urdf.rviz b/ros/t_top/rviz/urdf.rviz deleted file mode 100644 index d67eda91..00000000 --- a/ros/t_top/rviz/urdf.rviz +++ /dev/null @@ -1,329 +0,0 @@ -Panels: - - Class: rviz/Displays - Help Height: 78 - Name: Displays - Property Tree Widget: - Expanded: - - /Global Options1 - - /Status1 - - /RobotModel1 - - /TF1 - - /TF1/Tree1 - - /PointCloud21 - - /MapCloud1 - - /MarkerArray1 - - /PoseArray1 - - /Map1 - Splitter Ratio: 0.6360294222831726 - Tree Height: 741 - - Class: rviz/Selection - Name: Selection - - Class: rviz/Tool Properties - Expanded: - - /2D Pose Estimate1 - - /2D Nav Goal1 - - /Publish Point1 - Name: Tool Properties - Splitter Ratio: 0.5886790156364441 - - Class: rviz/Views - Expanded: - - /Current View1 - Name: Views - Splitter Ratio: 0.5 - - Class: rviz/Time - Experimental: false - Name: Time - SyncMode: 0 - SyncSource: MapCloud -Preferences: - PromptSaveOnExit: true -Toolbars: - toolButtonStyle: 2 -Visualization Manager: - Class: "" - Displays: - - Alpha: 0.5 - Cell Size: 1 - Class: rviz/Grid - Color: 160; 160; 164 - Enabled: true - Line Style: - Line Width: 0.029999999329447746 - Value: Lines - Name: Grid - Normal Cell Count: 0 - Offset: - X: 0 - Y: 0 - Z: 0 - Plane: XY - Plane Cell Count: 10 - Reference Frame: - Value: true - - Alpha: 1 - Class: rviz/RobotModel - Collision Enabled: false - Enabled: true - Links: - All Links Enabled: true - Expand Joint Details: false - Expand Link Details: false - Expand Tree: false - Link Tree Style: Links in Alphabetic Order - base_link: - Alpha: 1 - Show Axes: false - Show Trail: false - head: - Alpha: 1 - Show Axes: false - Show Trail: false - Value: true - stewart_base: - Alpha: 1 - Show Axes: false - Show Trail: false - Value: true - torso_base: - Alpha: 1 - Show Axes: false - Show Trail: false - Value: true - Name: RobotModel - Robot Description: robot_description - TF Prefix: "" - Update Interval: 0 - Value: true - Visual Enabled: true - - Class: rviz/TF - Enabled: true - Frame Timeout: 15 - Frames: - All Enabled: true - base_link: - Value: true - camera_aligned_depth_to_color_frame: - Value: true - camera_color_frame: - Value: true - camera_color_optical_frame: - Value: true - camera_depth_frame: - Value: true - camera_depth_optical_frame: - Value: true - camera_link: - Value: true - head: - Value: true - map: - Value: true - odas: - Value: true - opencr: - Value: true - opencr_imu: - Value: true - stewart_base: - Value: true - torso_base: - Value: true - Marker Alpha: 1 - Marker Scale: 0.10000000149011612 - Name: TF - Show Arrows: true - Show Axes: true - Show Names: true - Tree: - map: - base_link: - odas: - {} - torso_base: - stewart_base: - head: - camera_link: - camera_aligned_depth_to_color_frame: - {} - camera_depth_frame: - camera_color_frame: - camera_color_optical_frame: - {} - camera_depth_optical_frame: - {} - opencr: - opencr_imu: - {} - Update Interval: 0 - Value: true - - Alpha: 1 - Autocompute Intensity Bounds: true - Autocompute Value Bounds: - Max Value: 10 - Min Value: -10 - Value: true - Axis: Z - Channel Name: intensity - Class: rviz/PointCloud2 - Color: 255; 255; 255 - Color Transformer: RGB8 - Decay Time: 0 - Enabled: false - Invert Rainbow: false - Max Color: 255; 255; 255 - Max Intensity: 4096 - Min Color: 0; 0; 0 - Min Intensity: 0 - Name: PointCloud2 - Position Transformer: XYZ - Queue Size: 10 - Selectable: true - Size (Pixels): 3 - Size (m): 0.009999999776482582 - Style: Flat Squares - Topic: /cloud_map - Unreliable: false - Use Fixed Frame: true - Use rainbow: true - Value: false - - Alpha: 1 - Autocompute Intensity Bounds: true - Autocompute Value Bounds: - Max Value: 10 - Min Value: -10 - Value: true - Axis: Z - Channel Name: intensity - Class: rtabmap_rviz_plugins/MapCloud - Cloud decimation: 4 - Cloud from scan: false - Cloud max depth (m): 4 - Cloud min depth (m): 0 - Cloud voxel size (m): 0.009999999776482582 - Color: 255; 255; 255 - Color Transformer: RGB8 - Download graph: false - Download map: false - Download namespace: "" - Enabled: true - Filter ceiling (m): 0 - Filter floor (m): 0 - Invert Rainbow: false - Max Color: 255; 255; 255 - Max Intensity: 4096 - Min Color: 0; 0; 0 - Min Intensity: 0 - Name: MapCloud - Node filtering angle (degrees): 30 - Node filtering radius (m): 0 - Position Transformer: XYZ - Queue Size: 10 - Size (Pixels): 3 - Size (m): 0.009999999776482582 - Style: Flat Squares - Topic: /mapData - Unreliable: false - Use Fixed Frame: true - Use rainbow: true - Value: true - - Class: rviz/MarkerArray - Enabled: true - Marker Topic: /video_analysis_markers - Name: MarkerArray - Namespaces: - {} - Queue Size: 100 - Value: true - - Alpha: 1 - Arrow Length: 0.30000001192092896 - Axes Length: 0.30000001192092896 - Axes Radius: 0.009999999776482582 - Class: rviz/PoseArray - Color: 255; 25; 0 - Enabled: true - Head Length: 0.07000000029802322 - Head Radius: 0.029999999329447746 - Name: PoseArray - Queue Size: 10 - Shaft Length: 1 - Shaft Radius: 0.009999999776482582 - Shape: Arrow (3D) - Topic: /sst_poses - Unreliable: false - Value: true - - Alpha: 0.699999988079071 - Class: rviz/Map - Color Scheme: map - Draw Behind: false - Enabled: true - Name: Map - Topic: /grid_map - Unreliable: false - Use Timestamp: false - Value: true - Enabled: true - Global Options: - Background Color: 48; 48; 48 - Default Light: true - Fixed Frame: map - Frame Rate: 15 - Name: root - Tools: - - Class: rviz/Interact - Hide Inactive Objects: true - - Class: rviz/MoveCamera - - Class: rviz/Select - - Class: rviz/FocusCamera - - Class: rviz/Measure - - Class: rviz/SetInitialPose - Theta std deviation: 0.2617993950843811 - Topic: /initialpose - X std deviation: 0.5 - Y std deviation: 0.5 - - Class: rviz/SetGoal - Topic: /move_base_simple/goal - - Class: rviz/PublishPoint - Single click: true - Topic: /clicked_point - Value: true - Views: - Current: - Class: rviz/Orbit - Distance: 2.3403515815734863 - Enable Stereo Rendering: - Stereo Eye Separation: 0.05999999865889549 - Stereo Focal Distance: 1 - Swap Stereo Eyes: false - Value: false - Field of View: 0.7853981852531433 - Focal Point: - X: -0.4190443456172943 - Y: 0.5717824101448059 - Z: 0.5939364433288574 - Focal Shape Fixed Size: false - Focal Shape Size: 0.05000000074505806 - Invert Z Axis: false - Name: Current View - Near Clip Distance: 0.009999999776482582 - Pitch: 0.3747967779636383 - Target Frame: - Yaw: 2.8254096508026123 - Saved: ~ -Window Geometry: - Displays: - collapsed: false - Height: 1016 - Hide Left Dock: false - Hide Right Dock: false - QMainWindow State: 000000ff00000000fd0000000400000000000002bf00000370fc020000000bfb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000002700000370000000c900fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261fb0000000c00430061006d0065007200610000000275000001220000000000000000fb0000000a0049006d0061006700650000000300000000970000000000000000fb0000000a0049006d00610067006501000002a3000000f40000000000000000000000010000010f00000370fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073010000002700000370000000a400fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000007380000003efc0100000002fb0000000800540069006d0065010000000000000738000002eb00fffffffb0000000800540069006d006501000000000000045000000000000000000000035e0000037000000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000 - Selection: - collapsed: false - Time: - collapsed: false - Tool Properties: - collapsed: false - Views: - collapsed: false - Width: 1848 - X: 72 - Y: 27 diff --git a/ros/t_top/scripts/head_roll_image_rotation_node.py b/ros/t_top/scripts/head_roll_image_rotation_node.py index 654b68f8..6b770557 100755 --- a/ros/t_top/scripts/head_roll_image_rotation_node.py +++ b/ros/t_top/scripts/head_roll_image_rotation_node.py @@ -1,67 +1,67 @@ #!/usr/bin/env python3 import math -import threading import cv2 -import rospy +import rclpy +import rclpy.node + + from cv_bridge import CvBridge -from tf.transformations import euler_from_quaternion +from tf_transformations import euler_from_quaternion from sensor_msgs.msg import Image from daemon_ros_client.msg import MotorStatus -class HeadRollImageRotationNode: +class HeadRollImageRotationNode(rclpy.node.Node): def __init__(self): - import math - self._roll_angle_lock = threading.Lock() + super().__init__('head_roll_image_rotation_node') self._roll_angle_rad = 0.0 - self._cv_bridge = CvBridge() - self._image_pub = rospy.Publisher('output_image', Image, queue_size=1) + self._image_pub = self.create_publisher(Image, 'output_image', 1) - self._motor_status_sub = rospy.Subscriber('daemon/motor_status', MotorStatus, self._motor_status_cb, queue_size=1) - self._image_sub = rospy.Subscriber('input_image', Image, self._image_cb, queue_size=1) + self._motor_status_sub = self.create_subscription(MotorStatus, 'daemon/motor_status', self._motor_status_cb, 1) + self._image_sub = self.create_subscription(Image, 'input_image', self._image_cb, 1) def _motor_status_cb(self, msg): head_angles = euler_from_quaternion([msg.head_pose.orientation.x, msg.head_pose.orientation.y, msg.head_pose.orientation.z, msg.head_pose.orientation.w]) - with self._roll_angle_lock: - self._roll_angle_rad = head_angles[0] + self._roll_angle_rad = head_angles[0] def _image_cb(self, color_image_msg): color_image = self._cv_bridge.imgmsg_to_cv2(color_image_msg, 'bgr8') - with self._roll_angle_lock: - roll_angle_rad = self._roll_angle_rad - h, w, _ = color_image.shape - rotation_matrix = cv2.getRotationMatrix2D((w / 2, h / 2), -math.degrees(roll_angle_rad), 1.0) + rotation_matrix = cv2.getRotationMatrix2D((w / 2, h / 2), -math.degrees(self._roll_angle_rad), 1.0) rotated_color_image = cv2.warpAffine(color_image, rotation_matrix, (w, h)) rotated_color_image_msg = self._cv_bridge.cv2_to_imgmsg(rotated_color_image, 'bgr8') - rotated_color_image_msg.header.seq = color_image_msg.header.seq rotated_color_image_msg.header.stamp = color_image_msg.header.stamp self._image_pub.publish(rotated_color_image_msg) def run(self): - rospy.spin() + rclpy.spin(self) def main(): - rospy.init_node('head_roll_image_rotation_node') + rclpy.init() head_roll_image_rotation_node = HeadRollImageRotationNode() - head_roll_image_rotation_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + head_roll_image_rotation_node.run() + except KeyboardInterrupt: pass + finally: + head_roll_image_rotation_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/t_top/scripts/robot_status.py b/ros/t_top/scripts/robot_status.py index 72a713e4..7d3753f1 100755 --- a/ros/t_top/scripts/robot_status.py +++ b/ros/t_top/scripts/robot_status.py @@ -1,10 +1,13 @@ #!/usr/bin/env python3 -import rospy +import rclpy +import rclpy.node + import psutil import os import re import json + from opentera_webrtc_ros_msgs.msg import RobotStatus from std_msgs.msg import String, Float32, Bool from daemon_ros_client.msg import BaseStatus @@ -38,34 +41,29 @@ def get_command_output(cmd: List[str]) -> str: return p.communicate()[0].decode('utf-8') -class RobotStatusPublisher(): +class RobotStatusNode(rclpy.node.Node): def __init__(self): - rospy.init_node("robot_status_publisher") - - self.pub_rate = 1 - self.status_pub = rospy.Publisher( - '/robot_status', RobotStatus, queue_size=10) - self.status_webrtc_pub = rospy.Publisher( - '/webrtc_data_outgoing', String, queue_size=10) - - self.mic_volume_sub = rospy.Subscriber( - 'mic_volume', Float32, self._set_mic_volume_cb, queue_size=10) - self.mic_volume = 1 - self.enable_camera_sub = rospy.Subscriber( - 'enable_camera', Bool, self._set_enable_camera_cb, queue_size=10) + super().__init__('robot_status_publisher') + + self.pub_rate = 1.0 + self.status_pub = self.create_publisher(RobotStatus, '/robot_status', 10) + self.status_webrtc_pub = self.create_publisher(String, '/webrtc_data_outgoing', 10) + + self.mic_volume_sub = self.create_subscription(Float32, 'mic_volume', self._set_mic_volume_cb, 10) + self.mic_volume = 1.0 + self.enable_camera_sub = self.create_subscription(Bool, 'enable_camera', self._set_enable_camera_cb, 10) self.camera_enabled = True - self.volume_sub = rospy.Subscriber( - 'volume', Float32, self._set_volume_cb, queue_size=10) - self.volume = 1 + self.volume_sub = self.create_subscription(Float32, 'volume', self._set_volume_cb, 10) + self.volume = 1.0 self.io = psutil.net_io_counters(pernic=True) self.bytes_sent = 0 self.bytes_recv = 0 self.base_status = BaseStatusData() self.base_status_lock = Lock() - self.base_status_sub = rospy.Subscriber( - "daemon/base_status", - BaseStatus, self._base_status_cb, queue_size=1) + self.base_status_sub = self.create_subscription(BaseStatus, "daemon/base_status", self._base_status_cb, 1) + + self.status_timer = self.create_timer(1.0 / self.pub_rate, self.send_status) def get_ip_address(self, ifname: str) -> str: try: @@ -101,92 +99,99 @@ def _base_status_cb(self, msg): msg.is_battery_charging ) - def run(self): - rate = rospy.Rate(self.pub_rate) - while not rospy.is_shutdown(): - # Fill timestamp - status = RobotStatus() - status.header.stamp = rospy.Time.now() - - # Fill robot info - with self.base_status_lock: - status.battery_voltage = self.base_status.voltage - status.battery_current = self.base_status.current - status.battery_level = self.base_status.percentage - status.is_charging = self.base_status.is_plugged_in - - status.cpu_usage = psutil.cpu_percent() - status.mem_usage = psutil.virtual_memory().percent - status.disk_usage = self.get_disk_usage() - - status.mic_volume = self.mic_volume - status.is_camera_on = self.camera_enabled - status.volume = self.volume - - status.wifi_network = get_command_output(["iwgetid"]) - if status.wifi_network != "": - wifi_interface_name = status.wifi_network.split()[0] - - wifi_usage = get_command_output( - ["iwconfig", wifi_interface_name]) - wifi_strength_re = re.search( - r'Link Quality=(\d+)/(\d+)', wifi_usage) - if wifi_strength_re is not None and len(wifi_strength_re.groups()) == 2: - numerator = int(wifi_strength_re.group(1)) - denominator = int(wifi_strength_re.group(2)) - else: - numerator, denominator = (0, 1) - status.wifi_strength = numerator / denominator * 100 - status.local_ip = self.get_ip_address(wifi_interface_name) - - io_2 = psutil.net_io_counters(pernic=True) - status.upload_speed = (io_2[wifi_interface_name].bytes_sent - self.bytes_sent) * 8 - status.download_speed = (io_2[wifi_interface_name].bytes_recv - self.bytes_recv) * 8 - self.bytes_sent = io_2[wifi_interface_name].bytes_sent - self.bytes_recv = io_2[wifi_interface_name].bytes_recv + def send_status(self) -> None: + # Fill timestamp + status = RobotStatus() + status.header.stamp = self.get_clock().now().to_msg() + + # Fill robot info + with self.base_status_lock: + status.battery_voltage = self.base_status.voltage + status.battery_current = self.base_status.current + status.battery_level = self.base_status.percentage + status.is_charging = self.base_status.is_plugged_in + + status.cpu_usage = psutil.cpu_percent() + status.mem_usage = psutil.virtual_memory().percent + status.disk_usage = self.get_disk_usage() + + status.mic_volume = self.mic_volume + status.is_camera_on = self.camera_enabled + status.volume = self.volume + + wifi_network_interface = get_command_output(["iwgetid"]) + if wifi_network_interface != "": + wifi_interface_name = wifi_network_interface.split()[0] + status.wifi_network = wifi_network_interface.split('"')[1] + + wifi_usage = get_command_output( + ["iwconfig", wifi_interface_name]) + wifi_strength_re = re.search( + r'Link Quality=(\d+)/(\d+)', wifi_usage) + if wifi_strength_re is not None and len(wifi_strength_re.groups()) == 2: + numerator = int(wifi_strength_re.group(1)) + denominator = int(wifi_strength_re.group(2)) else: - status.wifi_strength = 0 - status.local_ip = '127.0.0.1' - status.upload_speed = 0 - status.download_speed = 0 - - # Publish for ROS - self.status_pub.publish(status) - - # Publish for webrtc - status_dict = { - 'type': 'robotStatus', - 'timestamp': status.header.stamp.secs, - 'status': { - 'isCharging': status.is_charging, - 'batteryVoltage': status.battery_voltage, - 'batteryCurrent': status.battery_current, - 'batteryLevel': status.battery_level, - 'cpuUsage': status.cpu_usage, - 'memUsage': status.mem_usage, - 'diskUsage': status.disk_usage, - 'wifiNetwork': status.wifi_network, - 'wifiStrength': status.wifi_strength, - 'uploadSpeed': status.upload_speed, - 'downloadSpeed': status.download_speed, - 'localIp': status.local_ip, - 'micVolume': status.mic_volume, - 'isCameraOn': status.is_camera_on, - 'volume': status.volume, - } + numerator, denominator = (0, 1) + status.wifi_strength = numerator / denominator * 100 + status.local_ip = self.get_ip_address(wifi_interface_name) + + io_2 = psutil.net_io_counters(pernic=True) + status.upload_speed = (io_2[wifi_interface_name].bytes_sent - self.bytes_sent) * 8.0 + status.download_speed = (io_2[wifi_interface_name].bytes_recv - self.bytes_recv) * 8.0 + self.bytes_sent = io_2[wifi_interface_name].bytes_sent + self.bytes_recv = io_2[wifi_interface_name].bytes_recv + else: + status.wifi_network = "" + status.wifi_strength = 0 + status.local_ip = '127.0.0.1' + status.upload_speed = 0 + status.download_speed = 0 + + # Publish for ROS + self.status_pub.publish(status) + + # Publish for webrtc + status_dict = { + 'type': 'robotStatus', + 'timestamp': status.header.stamp.sec, + 'status': { + 'isCharging': status.is_charging, + 'batteryVoltage': status.battery_voltage, + 'batteryCurrent': status.battery_current, + 'batteryLevel': status.battery_level, + 'cpuUsage': status.cpu_usage, + 'memUsage': status.mem_usage, + 'diskUsage': status.disk_usage, + 'wifiNetwork': status.wifi_network, + 'wifiStrength': status.wifi_strength, + 'uploadSpeed': status.upload_speed, + 'downloadSpeed': status.download_speed, + 'localIp': status.local_ip, + 'micVolume': status.mic_volume, + 'isCameraOn': status.is_camera_on, + 'volume': status.volume, } - self.status_webrtc_pub.publish(json.dumps(status_dict)) + } + self.status_webrtc_pub.publish(String(data=json.dumps(status_dict))) - if rospy.is_shutdown(): - break + def run(self): + rclpy.spin(self) - rate.sleep() +def main(): + rclpy.init() + robot_status_node = RobotStatusNode() -if __name__ == '__main__': - print("Robot Status Publisher Starting") try: - robot_status = RobotStatusPublisher() - robot_status.run() - except rospy.ROSInterruptException: + robot_status_node.run() + except KeyboardInterrupt: pass + finally: + robot_status_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/t_top/setup.py b/ros/t_top/setup.py deleted file mode 100644 index 5da6a0b9..00000000 --- a/ros/t_top/setup.py +++ /dev/null @@ -1,12 +0,0 @@ -## ! DO NOT MANUALLY INVOKE THIS setup.py, USE CATKIN INSTEAD - -from distutils.core import setup -from catkin_pkg.python_setup import generate_distutils_setup - -# fetch values from package.xml -setup_args = generate_distutils_setup( - packages=['t_top'], - package_dir={'': 'src'}, -) - -setup(**setup_args) diff --git a/ros/t_top/src/t_top/__init__.py b/ros/t_top/t_top/__init__.py similarity index 100% rename from ros/t_top/src/t_top/__init__.py rename to ros/t_top/t_top/__init__.py diff --git a/ros/t_top/src/t_top/movement_commands.py b/ros/t_top/t_top/movement_commands.py similarity index 87% rename from ros/t_top/src/t_top/movement_commands.py rename to ros/t_top/t_top/movement_commands.py index d30428b9..13872658 100644 --- a/ros/t_top/src/t_top/movement_commands.py +++ b/ros/t_top/t_top/movement_commands.py @@ -4,10 +4,13 @@ import math import time -import rospy -from tf.transformations import euler_from_quaternion, quaternion_from_euler import numpy as np +import rclpy +from rclpy.callback_groups import MutuallyExclusiveCallbackGroup + +from tf_transformations import euler_from_quaternion, quaternion_from_euler + from std_msgs.msg import Float32 from geometry_msgs.msg import PoseStamped from daemon_ros_client.msg import MotorStatus @@ -49,7 +52,9 @@ def abs_diff_torso_angle(a, b): class MovementCommands: - def __init__(self, simulation=False, namespace='daemon'): + def __init__(self, node, simulation=False, namespace='daemon'): + self.node = node + self._read_torso_lock = threading.Lock() self._read_head_lock = threading.Lock() @@ -64,14 +69,13 @@ def __init__(self, simulation=False, namespace='daemon'): if simulation: self._np_head_tolerances = np.array(3 * [0.07] + 3 * [0.1]) - self._hbba_filter_state = hbba_lite.OnOffHbbaFilterState( - 'pose/filter_state') - self._torso_orientation_pub = rospy.Publisher( - f'{namespace}/set_torso_orientation', Float32, queue_size=5) - self._head_pose_pub = rospy.Publisher( - f'{namespace}/set_head_pose', PoseStamped, queue_size=5) + self._hbba_filter_state = hbba_lite.OnOffHbbaFilterState(self.node, 'pose/filter_state') + self._torso_orientation_pub = self.node.create_publisher(Float32, f'{namespace}/set_torso_orientation', 5) + self._head_pose_pub = self.node.create_publisher(PoseStamped, f'{namespace}/set_head_pose', 5) - self._motor_status_sub = rospy.Subscriber('daemon/motor_status', MotorStatus, self._motor_status_cb, queue_size=1) + # Custom callback group in order to allow callbacks to be run in parallel + self._motor_status_sub = self.node.create_subscription(MotorStatus, 'daemon/motor_status', self._motor_status_cb, 1, + callback_group=MutuallyExclusiveCallbackGroup()) @property def is_filtering_all_messages(self): @@ -125,10 +129,10 @@ def move_torso_speed(self, speed_rad_sec_torso, should_sleep=True): torso_pose = self.current_torso_pose + steps_size_torso if abs(steps_size_torso) > 0: - self._torso_orientation_pub.publish(torso_pose) + self._torso_orientation_pub.publish(self._torso_msg(torso_pose)) if should_sleep: - rospy.sleep(self._minTime) + time.sleep(self._minTime) # Should be called in a loop def move_head_speed(self, speeds_head, should_sleep=True, current_head_pose=None): @@ -158,7 +162,10 @@ def move_head_speed(self, speeds_head, should_sleep=True, current_head_pose=None self._head_msg(head_pose) if should_sleep: - rospy.sleep(self._minTime) + time.sleep(self._minTime) + + def _torso_msg(self, pose): + return Float32(data=pose) def move_torso(self, pose, should_wait=False, speed_rad_sec=1.0e10, stop_cb=None, timeout=float('inf')): if self._hbba_filter_state.is_filtering_all_messages or (stop_cb and stop_cb()): @@ -188,13 +195,13 @@ def move_torso(self, pose, should_wait=False, speed_rad_sec=1.0e10, stop_cb=None return False steps_cumulative_size = i * steps_size offset = distance - steps_cumulative_size - self._torso_orientation_pub.publish(pose - offset) - rospy.sleep(self._minTime) - self._torso_orientation_pub.publish(pose) + self._torso_orientation_pub.publish(self._torso_msg(pose - offset)) + time.sleep(self._minTime) + self._torso_orientation_pub.publish(self._torso_msg(pose)) else: if self._hbba_filter_state.is_filtering_all_messages or (stop_cb and stop_cb()): return False - self._torso_orientation_pub.publish(pose) + self._torso_orientation_pub.publish(self._torso_msg(pose)) if should_wait: while abs_diff_torso_angle(pose, self.current_torso_pose) > 0.1: @@ -203,8 +210,8 @@ def move_torso(self, pose, should_wait=False, speed_rad_sec=1.0e10, stop_cb=None if (time.time() - start_time) > timeout: raise TimeoutError() - self._torso_orientation_pub.publish(pose) - rospy.sleep(self._minTime) + self._torso_orientation_pub.publish(self._torso_msg(pose)) + time.sleep(self._minTime) return True @@ -241,16 +248,16 @@ def _head_msg(self, pose): pose_msg = PoseStamped() pose_msg.header.frame_id = 'stewart_base' - pose_msg.pose.position.x = pose[0] - pose_msg.pose.position.y = pose[1] - pose_msg.pose.position.z = pose[2] + pose_msg.pose.position.x = float(pose[0]) + pose_msg.pose.position.y = float(pose[1]) + pose_msg.pose.position.z = float(pose[2]) q = quaternion_from_euler(pose[3], pose[4], pose[5]) - pose_msg.pose.orientation.x = q[0] - pose_msg.pose.orientation.y = q[1] - pose_msg.pose.orientation.z = q[2] - pose_msg.pose.orientation.w = q[3] + pose_msg.pose.orientation.x = float(q[0]) + pose_msg.pose.orientation.y = float(q[1]) + pose_msg.pose.orientation.z = float(q[2]) + pose_msg.pose.orientation.w = float(q[3]) self._head_pose_pub.publish(pose_msg) @@ -298,7 +305,7 @@ def move_head(self, pose, should_wait=False, np_offsets[j] = 0 self._head_msg(np_pose - np_offsets) - rospy.sleep(self._minTime) + time.sleep(self._minTime) self._head_msg(pose) else: if self._hbba_filter_state.is_filtering_all_messages or (stop_cb and stop_cb()): @@ -313,7 +320,7 @@ def move_head(self, pose, should_wait=False, raise TimeoutError() self._head_msg(pose) - rospy.sleep(self._minTime) + time.sleep(self._minTime) return True diff --git a/ros/t_top/urdf/ttop.urdf.xacro b/ros/t_top/urdf/ttop.urdf.xacro deleted file mode 100644 index 5d237887..00000000 --- a/ros/t_top/urdf/ttop.urdf.xacro +++ /dev/null @@ -1,154 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ros/tests/yolo_performance/CMakeLists.txt b/ros/tests/yolo_performance/CMakeLists.txt index d3ef61bc..01620fdc 100644 --- a/ros/tests/yolo_performance/CMakeLists.txt +++ b/ros/tests/yolo_performance/CMakeLists.txt @@ -1,208 +1,37 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(yolo_performance) -## Compile as C++11, supported in ROS Kinetic and newer -# add_compile_options(-std=c++11) -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - cv_bridge - dnn_utils - sensor_msgs - std_msgs -) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -# add_message_files( -# FILES -# Message1.msg -# Message2.msg -# ) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -# generate_messages( -# DEPENDENCIES -# sensor_msgs# std_msgs -# ) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( -# INCLUDE_DIRS include -# LIBRARIES yolo_performance -# CATKIN_DEPENDS cv_bridge dnn_utils sensor_msgs std_msgs -# DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( -# include - ${catkin_INCLUDE_DIRS} -) - -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/yolo_performance.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -# add_executable(${PROJECT_NAME}_node src/yolo_performance_node.cpp) +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() -## Specify libraries to link a library or executable target against -# target_link_libraries(${PROJECT_NAME}_node -# ${catkin_LIBRARIES} -# ) +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclpy REQUIRED) +find_package(cv_bridge REQUIRED) +find_package(dnn_utils REQUIRED) +find_package(sensor_msgs REQUIRED) +find_package(std_msgs REQUIRED) -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -catkin_install_python(PROGRAMS +# Python Nodes +install(PROGRAMS scripts/image_gathering_node.py scripts/processing_node.py - DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} + DESTINATION lib/${PROJECT_NAME} ) -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_yolo_performance.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() +# Launch files +install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}) -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/tests/yolo_performance/README.md b/ros/tests/yolo_performance/README.md index 09e09630..76bdf805 100644 --- a/ros/tests/yolo_performance/README.md +++ b/ros/tests/yolo_performance/README.md @@ -6,10 +6,11 @@ This folder folder contains the nodes to measure the performance of YOLO models. 1. Capture images by executing this command and following the printed instructions. ``` -roslaunch yolo_performance image_gathering.launch output_path:= dataset:= image_count:= camera_type:= +ros2 launch yolo_performance image_gathering.launch.xml output_path:= dataset:= image_count:= camera_type:= ``` +ros2 launch yolo_performance image_gathering.launch.xml output_path:=/home/introlab/test_yolo dataset:=coco image_count:=10 camera_type:=realsense 2. Process the images by executing this command. ``` -roslaunch yolo_performance processing.launch input_path:= dataset:= neural_network_inference_type:= +ros2 launch yolo_performance processing.launch.xml input_path:= dataset:= neural_network_inference_type:= ``` diff --git a/ros/tests/yolo_performance/launch/image_gathering.launch b/ros/tests/yolo_performance/launch/image_gathering.launch deleted file mode 100644 index 57bbbed2..00000000 --- a/ros/tests/yolo_performance/launch/image_gathering.launch +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [1m, 2m, 3m] - - - - [person, bowl, bottle] - - - - [person, bowl, bottle, tong] - - - - - - diff --git a/ros/tests/yolo_performance/launch/image_gathering.launch.xml b/ros/tests/yolo_performance/launch/image_gathering.launch.xml new file mode 100644 index 00000000..2f4945c8 --- /dev/null +++ b/ros/tests/yolo_performance/launch/image_gathering.launch.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ros/tests/yolo_performance/launch/processing.launch b/ros/tests/yolo_performance/launch/processing.launch deleted file mode 100644 index 522106b1..00000000 --- a/ros/tests/yolo_performance/launch/processing.launch +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - $(arg yolo_models) - - - - - diff --git a/ros/tests/yolo_performance/launch/processing.launch.xml b/ros/tests/yolo_performance/launch/processing.launch.xml new file mode 100644 index 00000000..1ba3f313 --- /dev/null +++ b/ros/tests/yolo_performance/launch/processing.launch.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/ros/tests/yolo_performance/package.xml b/ros/tests/yolo_performance/package.xml index 20736872..1fb036fa 100644 --- a/ros/tests/yolo_performance/package.xml +++ b/ros/tests/yolo_performance/package.xml @@ -1,71 +1,27 @@ - + + yolo_performance 0.0.0 The yolo_performance package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rclpy + cv_bridge + dnn_utils + sensor_msgs + std_msgs - - - - TODO + rosidl_default_runtime + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - cv_bridge - dnn_utils - sensor_msgs - std_msgs - cv_bridge - dnn_utils - sensor_msgs - std_msgs - cv_bridge - dnn_utils - sensor_msgs - std_msgs - - - - - + ament_cmake diff --git a/ros/tests/yolo_performance/scripts/image_gathering_node.py b/ros/tests/yolo_performance/scripts/image_gathering_node.py index aada79bc..6e123ad4 100755 --- a/ros/tests/yolo_performance/scripts/image_gathering_node.py +++ b/ros/tests/yolo_performance/scripts/image_gathering_node.py @@ -5,7 +5,8 @@ import cv2 -import rospy +import rclpy +import rclpy.node from cv_bridge import CvBridge @@ -16,12 +17,14 @@ ENTER_KEY_CODE = 13 -class ImageGatheringNode: +class ImageGatheringNode(rclpy.node.Node): def __init__(self): - self._output_path = os.path.expanduser(rospy.get_param('~output_path')) - self._image_count = rospy.get_param('~image_count') - self._setups = rospy.get_param('~setups') - self._classes = rospy.get_param('~classes') + super().__init__('image_gathering_node') + + self._output_path = os.path.expanduser(self.declare_parameter('output_path', '').get_parameter_value().string_value) + self._image_count = self.declare_parameter('image_count', 100).get_parameter_value().integer_value + self._setups = self.declare_parameter('setups', ['1m']).get_parameter_value().string_array_value + self._classes = self.declare_parameter('classes', ['people']).get_parameter_value().string_array_value self._current_image_index = 0 self._current_class_index = 0 @@ -32,7 +35,7 @@ def __init__(self): self._create_output_directories() self._cv_bridge = CvBridge() - self._image_sub = rospy.Subscriber('image_raw', Image, self._image_cb, queue_size=1) + self._image_sub = self.create_subscription(Image, 'image_raw', self._image_cb, 1) def _create_output_directories(self): for s in self._setups: @@ -46,7 +49,7 @@ def _image_cb(self, color_image_msg): if self._is_waiting and pressed_key == ENTER_KEY_CODE: self._is_waiting = False - print('Gathering images') + self.get_logger().info('Gathering images') elif not self._is_waiting and self._current_image_index < self._image_count: self._save_image(color_image) self._current_image_index += 1 @@ -61,7 +64,8 @@ def _image_cb(self, color_image_msg): if self._current_class_index < len(self._classes): self._print_current_class() else: - rospy.signal_shutdown("The gathering is finished.") + self.get_logger().info('The gathering is finished.') + rclpy.shutdown() def _display_image(self, color_image): scale = min(MAX_WINDOW_SIZE / color_image.shape[0], MAX_WINDOW_SIZE / color_image.shape[1]) @@ -76,25 +80,29 @@ def _save_image(self, color_image): cv2.imwrite(path, color_image) def _print_current_class(self): - print() - print(f'Waiting for {self._classes[self._current_class_index]} - {self._setups[self._current_setup_index]}') - print(f'Make sure only the object and at most one person are visible.') - print(f'Press enter to continue') + self.get_logger().info('') + self.get_logger().info(f'Waiting for {self._classes[self._current_class_index]} - {self._setups[self._current_setup_index]}') + self.get_logger().info(f'Make sure only the object and at most one person are visible.') + self.get_logger().info(f'Press enter to continue') def run(self): - rospy.spin() + rclpy.spin(self) def main(): - rospy.init_node('image_gathering_node') + rclpy.init() image_gathering_node = ImageGatheringNode() - image_gathering_node.run() - cv2.destroyAllWindows() + try: + image_gathering_node.run() + except KeyboardInterrupt: + pass + finally: + image_gathering_node.destroy_node() + cv2.destroyAllWindows() + if rclpy.ok(): + rclpy.shutdown() if __name__ == '__main__': - try: - main() - except rospy.ROSInterruptException: - pass + main() diff --git a/ros/tests/yolo_performance/scripts/processing_node.py b/ros/tests/yolo_performance/scripts/processing_node.py index 57cab209..0a4d5283 100755 --- a/ros/tests/yolo_performance/scripts/processing_node.py +++ b/ros/tests/yolo_performance/scripts/processing_node.py @@ -8,7 +8,8 @@ from tqdm import tqdm -import rospy +import rclpy +import rclpy.node from dnn_utils import Yolo @@ -57,14 +58,16 @@ def print(self, title): def main(): - rospy.init_node('processing_node') + rclpy.init() - input_path = rospy.get_param('~input_path') + node = rclpy.node.Node('processing_node') + + input_path = node.declare_parameter('input_path', '').get_parameter_value().string_value output_path = os.path.join(input_path, '..', 'results') - yolo_models = rospy.get_param('~yolo_models') - confidence_threshold = rospy.get_param('~confidence_threshold') - nms_threshold = rospy.get_param('~nms_threshold') - inference_type = rospy.get_param('~neural_network_inference_type') + yolo_models = node.declare_parameter('yolo_models', ['yolo_v4_coco']).get_parameter_value().string_array_value + confidence_threshold = node.declare_parameter('confidence_threshold', 0.5).get_parameter_value().double_value + nms_threshold = node.declare_parameter('nms_threshold', 0.5).get_parameter_value().double_value + inference_type = node.declare_parameter('neural_network_inference_type', 'cpu').get_parameter_value().string_value setups, classes = _load_setups_classes(input_path) performances_by_setup_by_model = _init_performances(yolo_models, setups, classes) @@ -188,5 +191,5 @@ def _get_bbox(object): if __name__ == '__main__': try: main() - except rospy.ROSInterruptException: + except KeyboardInterrupt: pass diff --git a/ros/user_interface/CMakeLists.txt b/ros/user_interface/CMakeLists.txt index fa5a422c..208d2800 100644 --- a/ros/user_interface/CMakeLists.txt +++ b/ros/user_interface/CMakeLists.txt @@ -1,192 +1,23 @@ -cmake_minimum_required(VERSION 2.8.3) - -if (POLICY CMP0048) - cmake_policy(SET CMP0048 NEW) -endif (POLICY CMP0048) - +cmake_minimum_required(VERSION 3.5) project(user_interface) -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS -# roscpp -) - -#STDC++ 11 -#set (CMAKE_CDD_STANDARD 11) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a run_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a run_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -# add_message_files( -# FILES -# Message1.msg -# Message2.msg -# ) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -# generate_messages( -# DEPENDENCIES -# std_msgs -# ) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a run_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if you package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( - # INCLUDE_DIRS include - # LIBRARIES webrtc - # CATKIN_DEPENDS roscpp std_msgs - # DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -# include_directories(include) -#include_directories( -# ${catkin_INCLUDE_DIRS} -#) - - -## Declare a C++ library -# add_library(webrtc -# src/${PROJECT_NAME}/webrtc.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(webrtc ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(webrtc_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -############# -## Install ## -############# +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -# install(PROGRAMS -# scripts/my_python_script -# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() -## Mark executables and/or libraries for installation -# install(TARGETS webrtc webrtc_gui_node -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_webrtc_gui.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() - -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +# Find dependencies +find_package(ament_cmake REQUIRED) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/node_modules.stamp @@ -211,6 +42,13 @@ add_custom_target( VERBATIM ) +# Shell scripts +install(PROGRAMS + scripts/web.sh + DESTINATION lib/${PROJECT_NAME} +) +install(DIRECTORY node_modules dist DESTINATION lib/${PROJECT_NAME}) + ####################### ## Required programs ## ####################### @@ -222,3 +60,5 @@ function(assert_program_installed PROGRAM) endfunction() assert_program_installed("npm") + +ament_package() diff --git a/ros/user_interface/README.md b/ros/user_interface/README.md index e4384cc0..b09c7792 100644 --- a/ros/user_interface/README.md +++ b/ros/user_interface/README.md @@ -19,7 +19,7 @@ npm run serve ## Published Topics -- `face/animation` ([std_msgs/String](http://docs.ros.org/en/noetic/api/std_msgs/html/msg/String.html)): Indicates the +- `face/animation` ([std_msgs/String](https://docs.ros.org/en/humble/p/std_msgs/interfaces/msg/String.html)): Indicates the actual animation. -- `face/mouth_signal_scale` ([std_msgs/Float32](http://docs.ros.org/en/noetic/api/std_msgs/html/msg/Float32.html)): +- `face/mouth_signal_scale` ([std_msgs/Float32](https://docs.ros.org/en/humble/p/std_msgs/interfaces/msg/Float32.html)): Indicates how much the mouth must be open. diff --git a/ros/user_interface/package-lock.json b/ros/user_interface/package-lock.json index 4d1926d0..5c320d71 100644 --- a/ros/user_interface/package-lock.json +++ b/ros/user_interface/package-lock.json @@ -3175,17 +3175,35 @@ } }, "node_modules/browserslist": { - "version": "4.6.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.6.tgz", - "integrity": "sha1-bkv0Z83lILydvfN0fa+gNTHOxFM=", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "caniuse-lite": "^1.0.30000984", - "electron-to-chromium": "^1.3.191", - "node-releases": "^1.1.25" + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" }, "bin": { "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, "node_modules/buffer": { @@ -3553,10 +3571,24 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30000985", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000985.tgz", - "integrity": "sha1-DrQPbIqMIZFVy+Q8SXXA77Sg938=", - "dev": true + "version": "1.0.30001625", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001625.tgz", + "integrity": "sha512-4KE9N2gcRH+HQhpeiRZXd+1niLB/XNLAhSy4z7fI8EzcbcPoAqjNInxVHTiTwWfTIV4w096XG8OtCOCQQKPv3w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] }, "node_modules/case-sensitive-paths-webpack-plugin": { "version": "2.2.0", @@ -5663,9 +5695,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.3.200", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.200.tgz", - "integrity": "sha1-ePuFi0ZiaejrRtMaUlYvAMhlEn8=", + "version": "1.4.788", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.788.tgz", + "integrity": "sha512-ubp5+Ev/VV8KuRoWnfP2QF2Bg+O2ZFdb49DiiNbz2VmgkIqrnyYaqIOqj8A6K/3p1xV0QcU5hBQ1+BmB6ot1OA==", "dev": true }, "node_modules/electron/node_modules/@types/node": { @@ -5910,6 +5942,15 @@ "node": ">= 0.4" } }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -7304,200 +7345,83 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "node_modules/fsevents": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", - "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", - "bundleDependencies": [ - "node-pre-gyp" - ], - "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "dependencies": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.12.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/fsevents/node_modules/abbrev": { + "node_modules/function-bind": { "version": "1.1.1", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true, - "inBundle": true, - "optional": true - }, - "node_modules/fsevents/node_modules/ansi-regex": { - "version": "2.1.1", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "inBundle": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=", + "dev": true }, - "node_modules/fsevents/node_modules/aproba": { - "version": "1.2.0", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true, - "inBundle": true, - "optional": true + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true }, - "node_modules/fsevents/node_modules/are-we-there-yet": { - "version": "1.1.5", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "node_modules/gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha1-xEFzPhO5J6yMD/C0w7Az8ogSkko=", "dev": true, - "inBundle": true, - "optional": true, "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" + "globule": "^1.0.0" + }, + "engines": { + "node": ">= 4.0.0" } }, - "node_modules/fsevents/node_modules/balanced-match": { - "version": "1.0.0", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true, - "inBundle": true, - "optional": true - }, - "node_modules/fsevents/node_modules/brace-expansion": { - "version": "1.1.11", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha1-T5RBKoLbMvNuOwuXQfipf+sDH34=", "dev": true, - "inBundle": true, - "optional": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/fsevents/node_modules/chownr": { - "version": "1.1.1", - "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", - "dev": true, - "inBundle": true, - "optional": true - }, - "node_modules/fsevents/node_modules/code-point-at": { - "version": "1.1.0", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "node_modules/get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", "dev": true, - "inBundle": true, - "optional": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/fsevents/node_modules/concat-map": { - "version": "0.0.1", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true, - "inBundle": true, - "optional": true - }, - "node_modules/fsevents/node_modules/console-control-strings": { - "version": "1.1.0", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true, - "inBundle": true, - "optional": true - }, - "node_modules/fsevents/node_modules/core-util-is": { - "version": "1.0.2", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true, - "inBundle": true, - "optional": true - }, - "node_modules/fsevents/node_modules/debug": { - "version": "4.1.1", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha1-wbJVV189wh1Zv8ec09K0axw6VLU=", "dev": true, - "inBundle": true, - "optional": true, "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/fsevents/node_modules/deep-extend": { - "version": "0.6.0", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "inBundle": true, - "optional": true, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/fsevents/node_modules/delegates": { - "version": "1.0.0", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true, - "inBundle": true, - "optional": true - }, - "node_modules/fsevents/node_modules/detect-libc": { - "version": "1.0.3", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "dev": true, - "inBundle": true, - "optional": true, - "bin": { - "detect-libc": "bin/detect-libc.js" + "pump": "^3.0.0" }, "engines": { - "node": ">=0.10" + "node": ">=6" } }, - "node_modules/fsevents/node_modules/fs-minipass": { - "version": "1.2.5", - "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", "dev": true, - "inBundle": true, - "optional": true, - "dependencies": { - "minipass": "^2.2.1" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/fsevents/node_modules/fs.realpath": { - "version": "1.0.0", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true, - "inBundle": true, - "optional": true - }, - "node_modules/fsevents/node_modules/gauge": { - "version": "2.7.4", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, - "inBundle": true, - "optional": true, "dependencies": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" + "assert-plus": "^1.0.0" } }, - "node_modules/fsevents/node_modules/glob": { - "version": "7.1.3", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "node_modules/glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha1-qmCKL2xXetNX4a5aXCbZqNGWklU=", "dev": true, - "inBundle": true, - "optional": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -7510,862 +7434,984 @@ "node": "*" } }, - "node_modules/fsevents/node_modules/has-unicode": { - "version": "2.0.1", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, - "inBundle": true, - "optional": true + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } }, - "node_modules/fsevents/node_modules/iconv-lite": { - "version": "0.4.24", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, - "inBundle": true, - "optional": true, "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "is-extglob": "^2.1.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/fsevents/node_modules/ignore-walk": { - "version": "3.0.1", - "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "node_modules/glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", + "dev": true + }, + "node_modules/global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", "dev": true, - "inBundle": true, - "optional": true, "dependencies": { - "minimatch": "^3.0.4" + "ini": "^1.3.4" + }, + "engines": { + "node": ">=4" } }, - "node_modules/fsevents/node_modules/inflight": { - "version": "1.0.6", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha1-q4eVM4hooLq9hSV1gBjCp+uVxC4=", "dev": true, - "inBundle": true, - "optional": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "engines": { + "node": ">=4" } }, - "node_modules/fsevents/node_modules/inherits": { - "version": "2.0.3", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "node_modules/globby": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", + "integrity": "sha1-/QKacGxwPSm90XD0tts6P3p8tj0=", "dev": true, - "inBundle": true, - "optional": true + "dependencies": { + "@types/glob": "^7.1.1", + "array-union": "^1.0.2", + "dir-glob": "^2.2.2", + "fast-glob": "^2.2.6", + "glob": "^7.1.3", + "ignore": "^4.0.3", + "pify": "^4.0.1", + "slash": "^2.0.0" + }, + "engines": { + "node": ">=6" + } }, - "node_modules/fsevents/node_modules/ini": { - "version": "1.3.5", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "deprecated": "Please update to ini >=1.3.6 to avoid a prototype pollution issue", + "node_modules/globby/node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha1-dQ49tYYgh7RzfrrIIH/9HvJ7Jfw=", "dev": true, - "inBundle": true, - "optional": true, "engines": { - "node": "*" + "node": ">= 4" } }, - "node_modules/fsevents/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "node_modules/globule": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", + "integrity": "sha1-Xf+xsZHyLSB5epNptJ6rTpg5aW0=", "dev": true, - "inBundle": true, - "optional": true, "dependencies": { - "number-is-nan": "^1.0.0" + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.10" } }, - "node_modules/fsevents/node_modules/isarray": { - "version": "1.0.0", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true, - "inBundle": true, - "optional": true - }, - "node_modules/fsevents/node_modules/minimatch": { - "version": "3.0.4", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha1-7fRefWf5lUVwXeH3u+7rEhdl7YU=", "dev": true, - "inBundle": true, - "optional": true, "dependencies": { - "brace-expansion": "^1.1.7" + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" }, "engines": { - "node": "*" + "node": ">=8.6" } }, - "node_modules/fsevents/node_modules/minimist": { - "version": "0.0.8", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true, - "inBundle": true, - "optional": true - }, - "node_modules/fsevents/node_modules/minipass": { - "version": "2.3.5", - "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", - "dev": true, - "inBundle": true, - "optional": true, - "dependencies": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } + "node_modules/graceful-fs": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz", + "integrity": "sha1-jY/cc5d8sEEEchy1NmbBymTNMos=", + "dev": true }, - "node_modules/fsevents/node_modules/minizlib": { - "version": "1.2.1", - "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", - "dev": true, - "inBundle": true, - "optional": true, - "dependencies": { - "minipass": "^2.2.1" - } + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha1-nPOmZcYkdHmJaDSvNc8du0QAdn4=", + "dev": true }, - "node_modules/fsevents/node_modules/mkdirp": { - "version": "0.5.1", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "node_modules/gzip-size": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz", + "integrity": "sha1-y5vuaS+HwGErIyhAqHOQTkwTUnQ=", "dev": true, - "inBundle": true, - "optional": true, "dependencies": { - "minimist": "0.0.8" + "duplexer": "^0.1.1", + "pify": "^4.0.1" }, - "bin": { - "mkdirp": "bin/cmd.js" + "engines": { + "node": ">=6" } }, - "node_modules/fsevents/node_modules/ms": { - "version": "2.1.1", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "node_modules/handle-thing": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz", + "integrity": "sha1-DgOWlf9QyT/CiFV9aW88HcZ3Z1Q=", + "dev": true + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", "dev": true, - "inBundle": true, - "optional": true + "engines": { + "node": ">=4" + } }, - "node_modules/fsevents/node_modules/needle": { - "version": "2.3.0", - "integrity": "sha512-QBZu7aAFR0522EyaXZM0FZ9GLpq6lvQ3uq8gteiDUp7wKdy0lSd2hPlgFwVuW1CBkfEs9PfDQsQzZghLs/psdg==", + "node_modules/har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha1-HvievT5JllV2de7ZiTEQ3DUPoIA=", + "deprecated": "this library is no longer supported", "dev": true, - "inBundle": true, - "optional": true, "dependencies": { - "debug": "^4.1.0", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - }, - "bin": { - "needle": "bin/needle" + "ajv": "^6.5.5", + "har-schema": "^2.0.0" }, "engines": { - "node": ">= 4.4.x" + "node": ">=6" } }, - "node_modules/fsevents/node_modules/node-pre-gyp": { - "version": "0.12.0", - "integrity": "sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==", - "deprecated": "Please upgrade to @mapbox/node-pre-gyp: the non-scoped node-pre-gyp package is deprecated and only the @mapbox scoped package will recieve updates in the future", + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=", "dev": true, - "inBundle": true, - "optional": true, "dependencies": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" + "function-bind": "^1.1.1" }, - "bin": { - "node-pre-gyp": "bin/node-pre-gyp" + "engines": { + "node": ">= 0.4.0" } }, - "node_modules/fsevents/node_modules/nopt": { - "version": "4.0.1", - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, - "inBundle": true, - "optional": true, "dependencies": { - "abbrev": "1", - "osenv": "^0.1.4" + "ansi-regex": "^2.0.0" }, - "bin": { - "nopt": "bin/nopt.js" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/fsevents/node_modules/npm-bundled": { - "version": "1.0.6", - "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", - "dev": true, - "inBundle": true, - "optional": true - }, - "node_modules/fsevents/node_modules/npm-packlist": { - "version": "1.4.1", - "integrity": "sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==", + "node_modules/has-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true, - "inBundle": true, - "optional": true, - "dependencies": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/fsevents/node_modules/npmlog": { - "version": "4.1.2", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "inBundle": true, - "optional": true, + "node_modules/has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", "dependencies": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" + "isarray": "2.0.1" } }, - "node_modules/fsevents/node_modules/number-is-nan": { - "version": "1.0.1", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "node_modules/has-binary2/node_modules/isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" + }, + "node_modules/has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true, - "inBundle": true, - "optional": true, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/fsevents/node_modules/object-assign": { - "version": "4.1.1", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "node_modules/has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", "dev": true, - "inBundle": true, - "optional": true, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, - "node_modules/fsevents/node_modules/once": { - "version": "1.4.0", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "node_modules/has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "dev": true, - "inBundle": true, - "optional": true, "dependencies": { - "wrappy": "1" - } - }, - "node_modules/fsevents/node_modules/os-homedir": { - "version": "1.0.2", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true, - "inBundle": true, - "optional": true, + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/fsevents/node_modules/os-tmpdir": { - "version": "1.0.2", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "node_modules/has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, - "inBundle": true, - "optional": true, + "dependencies": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/fsevents/node_modules/osenv": { - "version": "0.1.5", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "node_modules/has-values/node_modules/kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, - "inBundle": true, - "optional": true, "dependencies": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "node_modules/fsevents/node_modules/path-is-absolute": { - "version": "1.0.1", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "inBundle": true, - "optional": true, + "is-buffer": "^1.1.5" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/fsevents/node_modules/process-nextick-args": { - "version": "2.0.0", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "node_modules/has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha1-E34RNUp7W/EapctknPDG8/8rLnc=", "dev": true, - "inBundle": true, - "optional": true + "engines": { + "node": ">=8" + } }, - "node_modules/fsevents/node_modules/rc": { - "version": "1.2.8", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "node_modules/hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", "dev": true, - "inBundle": true, - "optional": true, "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" }, - "bin": { - "rc": "cli.js" + "engines": { + "node": ">=4" } }, - "node_modules/fsevents/node_modules/rc/node_modules/minimist": { - "version": "1.2.0", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true, - "inBundle": true, - "optional": true + "node_modules/hash-sum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", + "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", + "dev": true }, - "node_modules/fsevents/node_modules/readable-stream": { - "version": "2.3.6", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha1-C6vKU46NTuSg+JiNaIZlN6ADz0I=", "dev": true, - "inBundle": true, - "optional": true, "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" } }, - "node_modules/fsevents/node_modules/rimraf": { - "version": "2.6.3", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha1-hK5l+n6vsWX922FWauFLrwVmTw8=", "dev": true, - "inBundle": true, - "optional": true, - "dependencies": { - "glob": "^7.1.3" - }, "bin": { - "rimraf": "bin.js" + "he": "bin/he" } }, - "node_modules/fsevents/node_modules/safe-buffer": { - "version": "5.1.2", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "inBundle": true, - "optional": true - }, - "node_modules/fsevents/node_modules/safer-buffer": { - "version": "2.1.2", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "inBundle": true, - "optional": true + "node_modules/hex-color-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", + "integrity": "sha1-TAb8y0YC/iYCs8k9+C1+fb8aio4=", + "dev": true }, - "node_modules/fsevents/node_modules/sax": { - "version": "1.2.4", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "node_modules/highlight.js": { + "version": "9.15.8", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.8.tgz", + "integrity": "sha1-80T9oSPzbxplSQ6TLPkFaeSZmXE=", + "deprecated": "Version no longer supported. Upgrade to @latest", "dev": true, - "inBundle": true, - "optional": true + "engines": { + "node": "*" + } }, - "node_modules/fsevents/node_modules/semver": { - "version": "5.7.0", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", "dev": true, - "inBundle": true, - "optional": true, - "bin": { - "semver": "bin/semver" + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" } }, - "node_modules/fsevents/node_modules/set-blocking": { - "version": "2.0.0", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "node_modules/hoopy": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", + "integrity": "sha1-YJIH1mEQADOpqUAq096mdzgcGx0=", "dev": true, - "inBundle": true, - "optional": true + "engines": { + "node": ">= 6.0.0" + } }, - "node_modules/fsevents/node_modules/signal-exit": { - "version": "3.0.2", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true, - "inBundle": true, - "optional": true + "node_modules/hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha1-l/I2l3vW4SVAiTD/bePuxigewEc=", + "dev": true }, - "node_modules/fsevents/node_modules/string_decoder": { - "version": "1.1.1", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", "dev": true, - "inBundle": true, - "optional": true, "dependencies": { - "safe-buffer": "~5.1.0" + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" } }, - "node_modules/fsevents/node_modules/string-width": { - "version": "1.0.2", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "node_modules/hsl-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz", + "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=", + "dev": true + }, + "node_modules/hsla-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", + "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=", + "dev": true + }, + "node_modules/html-comment-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", + "integrity": "sha1-l9RoiutcgYhqNk+qDK0d2hTUM6c=", + "dev": true + }, + "node_modules/html-entities": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", + "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", "dev": true, - "inBundle": true, - "optional": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } + "engines": [ + "node >= 0.4.0" + ] }, - "node_modules/fsevents/node_modules/strip-ansi": { - "version": "3.0.1", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "node_modules/html-minifier": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", + "integrity": "sha1-0AQOBUcw41TbAIRjWTGUAVIS0gw=", "dev": true, - "inBundle": true, - "optional": true, "dependencies": { - "ansi-regex": "^2.0.0" + "camel-case": "3.0.x", + "clean-css": "4.2.x", + "commander": "2.17.x", + "he": "1.2.x", + "param-case": "2.1.x", + "relateurl": "0.2.x", + "uglify-js": "3.4.x" + }, + "bin": { + "html-minifier": "cli.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/fsevents/node_modules/strip-json-comments": { - "version": "2.0.1", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "node_modules/html-minifier/node_modules/commander": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha1-vXerfebelCBc6sxy8XFtKfIKd78=", + "dev": true + }, + "node_modules/html-tags": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", + "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=", "dev": true, - "inBundle": true, - "optional": true, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/fsevents/node_modules/tar": { - "version": "4.4.8", - "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", + "node_modules/html-webpack-plugin": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz", + "integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s=", + "deprecated": "3.x is no longer supported", "dev": true, - "inBundle": true, - "optional": true, "dependencies": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" + "html-minifier": "^3.2.3", + "loader-utils": "^0.2.16", + "lodash": "^4.17.3", + "pretty-error": "^2.0.2", + "tapable": "^1.0.0", + "toposort": "^1.0.0", + "util.promisify": "1.0.0" }, "engines": { - "node": ">=4.5" + "node": ">=6.9" + }, + "peerDependencies": { + "webpack": "^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0" } }, - "node_modules/fsevents/node_modules/util-deprecate": { - "version": "1.0.2", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "node_modules/html-webpack-plugin/node_modules/big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha1-pfwpi4G54Nyi5FiCR4S2XFK6WI4=", "dev": true, - "inBundle": true, - "optional": true + "engines": { + "node": "*" + } }, - "node_modules/fsevents/node_modules/wide-align": { - "version": "1.1.3", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "node_modules/html-webpack-plugin/node_modules/json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/html-webpack-plugin/node_modules/loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", "dev": true, - "inBundle": true, - "optional": true, "dependencies": { - "string-width": "^1.0.2 || 2" + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" } }, - "node_modules/fsevents/node_modules/wrappy": { - "version": "1.0.2", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "node_modules/htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha1-vWedw/WYl7ajS7EHSchVu1OpOS8=", "dev": true, - "inBundle": true, - "optional": true + "dependencies": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + } }, - "node_modules/fsevents/node_modules/yallist": { - "version": "3.0.3", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "node_modules/htmlparser2/node_modules/readable-stream": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", + "integrity": "sha1-pRwmdUZY4KPCHb9ZFjvUW6b0R/w=", "dev": true, - "inBundle": true, - "optional": true + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=", + "node_modules/http-cache-semantics": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz", + "integrity": "sha1-SVcEdzJ37u9uQ/mrLCx9JZ3aJcU=", "dev": true }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", "dev": true }, - "node_modules/gaze": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", - "integrity": "sha1-xEFzPhO5J6yMD/C0w7Az8ogSkko=", + "node_modules/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha1-T1ApzxMjnzEDblsuVSkrz7zIXI8=", "dev": true, "dependencies": { - "globule": "^1.0.0" + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" }, "engines": { - "node": ">= 4.0.0" + "node": ">= 0.6" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha1-T5RBKoLbMvNuOwuXQfipf+sDH34=", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } + "node_modules/http-errors/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true }, - "node_modules/get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "node_modules/http-parser-js": { + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz", + "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=", + "dev": true + }, + "node_modules/http-proxy": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", + "integrity": "sha1-etOElGWPhGBeL220Q230EPTlvpo=", "dev": true, + "dependencies": { + "eventemitter3": "^3.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=4.0.0" } }, - "node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha1-wbJVV189wh1Zv8ec09K0axw6VLU=", + "node_modules/http-proxy-middleware": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", + "integrity": "sha1-GDx9xKoUeRUDBkmMIQza+WCApDo=", "dev": true, "dependencies": { - "pump": "^3.0.0" + "http-proxy": "^1.17.0", + "is-glob": "^4.0.0", + "lodash": "^4.17.11", + "micromatch": "^3.1.10" }, "engines": { - "node": ">=6" + "node": ">=4.0.0" } }, - "node_modules/get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "dev": true, + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=0.8", + "npm": ">=1.3.7" } }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "node_modules/https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" + "engines": { + "node": ">=10.17.0" } }, - "node_modules/glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha1-qmCKL2xXetNX4a5aXCbZqNGWklU=", + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha1-ICK0sl+93CHS9SSXSkdKr+czkIs=", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { - "node": "*" + "node": ">=0.10.0" } }, - "node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "node_modules/icss-replace-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", + "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", + "dev": true + }, + "node_modules/icss-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", + "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", "dev": true, "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" + "postcss": "^6.0.1" } }, - "node_modules/glob-parent/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "node_modules/icss-utils/node_modules/postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha1-YcgswyisYOZ3ZF+XkFTrmLwOMyQ=", "dev": true, "dependencies": { - "is-extglob": "^2.1.0" + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/icss-utils/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/glob-to-regexp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", - "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha1-7BaFWOlaoYH9h9N/VcMrvLZwi4Q=", "dev": true }, - "node_modules/global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "node_modules/iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, + "node_modules/ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha1-Cpf7h2mG6AgcYxFg+PnziRV/AEM=", + "dev": true + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", + "dev": true + }, + "node_modules/import-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", + "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", "dev": true, "dependencies": { - "ini": "^1.3.4" + "import-from": "^2.1.0" }, "engines": { "node": ">=4" } }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha1-q4eVM4hooLq9hSV1gBjCp+uVxC4=", + "node_modules/import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", "dev": true, + "dependencies": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + }, "engines": { "node": ">=4" } }, - "node_modules/globby": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", - "integrity": "sha1-/QKacGxwPSm90XD0tts6P3p8tj0=", + "node_modules/import-fresh/node_modules/caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", "dev": true, "dependencies": { - "@types/glob": "^7.1.1", - "array-union": "^1.0.2", - "dir-glob": "^2.2.2", - "fast-glob": "^2.2.6", - "glob": "^7.1.3", - "ignore": "^4.0.3", - "pify": "^4.0.1", - "slash": "^2.0.0" + "caller-callsite": "^2.0.0" }, "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/globby/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha1-dQ49tYYgh7RzfrrIIH/9HvJ7Jfw=", + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", "dev": true, "engines": { - "node": ">= 4" + "node": ">=4" } }, - "node_modules/globule": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", - "integrity": "sha1-Xf+xsZHyLSB5epNptJ6rTpg5aW0=", + "node_modules/import-from": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", + "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", "dev": true, "dependencies": { - "glob": "~7.1.1", - "lodash": "~4.17.10", - "minimatch": "~3.0.2" + "resolve-from": "^3.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">=4" } }, - "node_modules/got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha1-7fRefWf5lUVwXeH3u+7rEhdl7YU=", + "node_modules/import-from/node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", "dev": true, - "dependencies": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - }, "engines": { - "node": ">=8.6" + "node": ">=4" } }, - "node_modules/graceful-fs": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz", - "integrity": "sha1-jY/cc5d8sEEEchy1NmbBymTNMos=", - "dev": true - }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha1-nPOmZcYkdHmJaDSvNc8du0QAdn4=", - "dev": true + "node_modules/import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true, + "engines": { + "node": ">=4" + } }, - "node_modules/gzip-size": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz", - "integrity": "sha1-y5vuaS+HwGErIyhAqHOQTkwTUnQ=", + "node_modules/import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha1-VQcL44pZk88Y72236WH1vuXFoJ0=", "dev": true, "dependencies": { - "duplexer": "^0.1.1", - "pify": "^4.0.1" + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" }, "engines": { "node": ">=6" } }, - "node_modules/handle-thing": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz", - "integrity": "sha1-DgOWlf9QyT/CiFV9aW88HcZ3Z1Q=", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "dependencies": { + "repeating": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", "dev": true }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "node_modules/indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w=", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc=", + "deprecated": "Please update to ini >=1.3.6 to avoid a prototype pollution issue", "dev": true, "engines": { - "node": ">=4" + "node": "*" } }, - "node_modules/har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha1-HvievT5JllV2de7ZiTEQ3DUPoIA=", - "deprecated": "this library is no longer supported", + "node_modules/inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha1-ndLyrXZdyrH/BEO0kUQqILoifck=", "dev": true, "dependencies": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" - }, + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.0.4", + "figures": "^2.0.0", + "lodash": "^4.3.0", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rx-lite": "^4.0.8", + "rx-lite-aggregates": "^4.0.8", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" + } + }, + "node_modules/inquirer/node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true, "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=", + "node_modules/inquirer/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "dependencies": { - "function-bind": "^1.1.1" + "ansi-regex": "^3.0.0" }, "engines": { - "node": ">= 0.4.0" + "node": ">=4" } }, - "node_modules/has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "node_modules/internal-ip": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", + "integrity": "sha1-hFRSuq2dLKO2nGNaE3rLmg2tCQc=", "dev": true, "dependencies": { - "ansi-regex": "^2.0.0" + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/has-ansi/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "node_modules/internal-ip/node_modules/default-gateway": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", + "integrity": "sha1-FnEEx1AMIRX23WmwpTa7jtcgVSs=", "dev": true, + "dependencies": { + "execa": "^1.0.0", + "ip-regex": "^2.1.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/has-binary2": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", - "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha1-YQ88ksk1nOHbYW5TgAjSP/NRWOY=", + "dev": true, "dependencies": { - "isarray": "2.0.1" + "loose-envify": "^1.0.0" } }, - "node_modules/has-binary2/node_modules/isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" + "node_modules/invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha1-c5P1r6Weyf9fZ6J2INEcIm4+7AI=", + "dev": true, + "engines": { + "node": ">=4" + } }, - "node_modules/has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" + "node_modules/ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "node_modules/ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", "dev": true, "engines": { "node": ">=4" } }, - "node_modules/has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "node_modules/ipaddr.js": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", + "integrity": "sha1-N9905DCg5HVQ/lSi3v4w2KzZX2U=", "dev": true, "engines": { - "node": ">= 0.4" + "node": ">= 0.10" } }, - "node_modules/has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "node_modules/is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", + "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", "dev": true, - "dependencies": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, "engines": { "node": ">=0.10.0" } }, - "node_modules/has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "dependencies": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" + "kind-of": "^3.0.2" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/has-values/node_modules/kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "dependencies": { "is-buffer": "^1.1.5" @@ -8374,3319 +8420,3042 @@ "node": ">=0.10.0" } }, - "node_modules/has-yarn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", - "integrity": "sha1-E34RNUp7W/EapctknPDG8/8rLnc=", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", "dev": true, "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "binary-extensions": "^1.0.0" }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", "dev": true }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha1-C6vKU46NTuSg+JiNaIZlN6ADz0I=", + "node_modules/is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha1-HhrfIZ4e62hNaR+dagX/DTCiTXU=", "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" + "engines": { + "node": ">= 0.4" } }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha1-hK5l+n6vsWX922FWauFLrwVmTw8=", + "node_modules/is-ci": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", + "integrity": "sha1-43ecjuF/zPQoSI9uKBGH8uYyhBw=", "dev": true, + "dependencies": { + "ci-info": "^1.5.0" + }, "bin": { - "he": "bin/he" + "is-ci": "bin.js" } }, - "node_modules/hex-color-regex": { + "node_modules/is-color-stop": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", - "integrity": "sha1-TAb8y0YC/iYCs8k9+C1+fb8aio4=", - "dev": true - }, - "node_modules/highlight.js": { - "version": "9.15.8", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.8.tgz", - "integrity": "sha1-80T9oSPzbxplSQ6TLPkFaeSZmXE=", - "deprecated": "Version no longer supported. Upgrade to @latest", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", + "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=", "dev": true, "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" + "css-color-names": "^0.0.4", + "hex-color-regex": "^1.1.0", + "hsl-regex": "^1.0.0", + "hsla-regex": "^1.0.0", + "rgb-regex": "^1.0.1", + "rgba-regex": "^1.0.0" } }, - "node_modules/hoopy": { + "node_modules/is-data-descriptor": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", - "integrity": "sha1-YJIH1mEQADOpqUAq096mdzgcGx0=", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, "engines": { - "node": ">= 6.0.0" + "node": ">=0.10.0" } }, - "node_modules/hosted-git-info": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha1-l/I2l3vW4SVAiTD/bePuxigewEc=", - "dev": true - }, - "node_modules/hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "dependencies": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/hsl-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz", - "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=", - "dev": true - }, - "node_modules/hsla-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", - "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=", - "dev": true - }, - "node_modules/html-comment-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", - "integrity": "sha1-l9RoiutcgYhqNk+qDK0d2hTUM6c=", - "dev": true - }, - "node_modules/html-entities": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", - "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", + "node_modules/is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", "dev": true, - "engines": [ - "node >= 0.4.0" - ] + "engines": { + "node": ">= 0.4" + } }, - "node_modules/html-minifier": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", - "integrity": "sha1-0AQOBUcw41TbAIRjWTGUAVIS0gw=", + "node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", "dev": true, "dependencies": { - "camel-case": "3.0.x", - "clean-css": "4.2.x", - "commander": "2.17.x", - "he": "1.2.x", - "param-case": "2.1.x", - "relateurl": "0.2.x", - "uglify-js": "3.4.x" - }, - "bin": { - "html-minifier": "cli.js" + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/html-minifier/node_modules/commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha1-vXerfebelCBc6sxy8XFtKfIKd78=", - "dev": true + "node_modules/is-descriptor/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/html-tags": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", - "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=", + "node_modules/is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", "dev": true, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/html-webpack-plugin": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz", - "integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s=", - "deprecated": "3.x is no longer supported", + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "dev": true, - "dependencies": { - "html-minifier": "^3.2.3", - "loader-utils": "^0.2.16", - "lodash": "^4.17.3", - "pretty-error": "^2.0.2", - "tapable": "^1.0.0", - "toposort": "^1.0.0", - "util.promisify": "1.0.0" + "bin": { + "is-docker": "cli.js" }, "engines": { - "node": ">=6.9" + "node": ">=8" }, - "peerDependencies": { - "webpack": "^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/html-webpack-plugin/node_modules/big.js": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha1-pfwpi4G54Nyi5FiCR4S2XFK6WI4=", + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", "dev": true, "engines": { - "node": "*" + "node": ">=0.10.0" } }, - "node_modules/html-webpack-plugin/node_modules/json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true, - "bin": { - "json5": "lib/cli.js" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/html-webpack-plugin/node_modules/loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "node_modules/is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", "dev": true, "dependencies": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0", - "object-assign": "^4.0.1" - } - }, - "node_modules/htmlparser2": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", - "integrity": "sha1-vWedw/WYl7ajS7EHSchVu1OpOS8=", - "dev": true, - "dependencies": { - "domelementtype": "^1.3.1", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^3.1.1" - } - }, - "node_modules/htmlparser2/node_modules/readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha1-pRwmdUZY4KPCHb9ZFjvUW6b0R/w=", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "number-is-nan": "^1.0.0" }, "engines": { - "node": ">= 6" + "node": ">=0.10.0" } }, - "node_modules/http-cache-semantics": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz", - "integrity": "sha1-SVcEdzJ37u9uQ/mrLCx9JZ3aJcU=", - "dev": true - }, - "node_modules/http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", - "dev": true - }, - "node_modules/http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha1-T1ApzxMjnzEDblsuVSkrz7zIXI8=", + "node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, "engines": { - "node": ">= 0.6" + "node": ">=4" } }, - "node_modules/http-errors/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "node_modules/http-parser-js": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz", - "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=", - "dev": true - }, - "node_modules/http-proxy": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", - "integrity": "sha1-etOElGWPhGBeL220Q230EPTlvpo=", + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha1-dWfb6fL14kZ7x3q4PEopSCQHpdw=", "dev": true, "dependencies": { - "eventemitter3": "^3.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">=4.0.0" + "node": ">=0.10.0" } }, - "node_modules/http-proxy-middleware": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", - "integrity": "sha1-GDx9xKoUeRUDBkmMIQza+WCApDo=", + "node_modules/is-installed-globally": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", + "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", "dev": true, "dependencies": { - "http-proxy": "^1.17.0", - "is-glob": "^4.0.0", - "lodash": "^4.17.11", - "micromatch": "^3.1.10" + "global-dirs": "^0.1.0", + "is-path-inside": "^1.0.0" }, "engines": { - "node": ">=4.0.0" + "node": ">=4" } }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "node_modules/is-installed-globally/node_modules/is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", "dev": true, "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" + "path-is-inside": "^1.0.1" }, "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" + "node": ">=0.10.0" } }, - "node_modules/https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", - "dev": true - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "node_modules/is-npm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-3.0.0.tgz", + "integrity": "sha1-7JFHv7YpxD9JTPZ5Nqlh7ex+gFM=", "dev": true, "engines": { - "node": ">=10.17.0" + "node": ">=8" } }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha1-ICK0sl+93CHS9SSXSkdKr+czkIs=", + "node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "kind-of": "^3.0.2" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/icss-replace-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", - "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", - "dev": true - }, - "node_modules/icss-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", - "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", - "dev": true, - "dependencies": { - "postcss": "^6.0.1" - } - }, - "node_modules/icss-utils/node_modules/postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha1-YcgswyisYOZ3ZF+XkFTrmLwOMyQ=", + "node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "dependencies": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" + "is-buffer": "^1.1.5" }, "engines": { - "node": ">=4.0.0" + "node": ">=0.10.0" } }, - "node_modules/icss-utils/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "node_modules/is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha1-7BaFWOlaoYH9h9N/VcMrvLZwi4Q=", - "dev": true - }, - "node_modules/iferr": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", - "dev": true - }, - "node_modules/ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha1-Cpf7h2mG6AgcYxFg+PnziRV/AEM=", - "dev": true - }, - "node_modules/immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", - "dev": true - }, - "node_modules/import-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", - "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", + "node_modules/is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha1-Z9Q7gmZKe1GR/ZEZEn6zAASKn9s=", "dev": true, - "dependencies": { - "import-from": "^2.1.0" - }, "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "node_modules/is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha1-v+Lcomxp85cmWkAJljYCk1oFOss=", "dev": true, "dependencies": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" + "is-path-inside": "^2.1.0" }, "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/import-fresh/node_modules/caller-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", - "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "node_modules/is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha1-fJgQWH1lmkDSe8201WFuqwWUlLI=", "dev": true, "dependencies": { - "caller-callsite": "^2.0.0" + "path-is-inside": "^1.0.2" }, "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", "dev": true, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/import-from": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", - "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", "dev": true, "dependencies": { - "resolve-from": "^3.0.0" + "isobject": "^3.0.1" }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/import-from/node_modules/resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "node_modules/is-port-reachable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-port-reachable/-/is-port-reachable-4.0.0.tgz", + "integrity": "sha512-9UoipoxYmSk6Xy7QFgRv2HDyaysmgSG75TFQs6S+3pDM7ZhKTF/bskZV+0UlABHzKjNVhPjYCLfeZUEg1wXxig==", "dev": true, "engines": { - "node": ">=4" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/import-lazy": { + "node_modules/is-promise": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", - "dev": true, - "engines": { - "node": ">=4" - } + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true }, - "node_modules/import-local": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", - "integrity": "sha1-VQcL44pZk88Y72236WH1vuXFoJ0=", + "node_modules/is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", "dev": true, "dependencies": { - "pkg-dir": "^3.0.0", - "resolve-cwd": "^2.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" + "has": "^1.0.1" }, "engines": { - "node": ">=6" + "node": ">= 0.4" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "node_modules/is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha1-+xj4fOH+uSUWnJpAfBkxijIG7Yg=", + "dev": true + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true, "engines": { - "node": ">=0.8.19" + "node": ">=0.10.0" } }, - "node_modules/indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "node_modules/is-svg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz", + "integrity": "sha1-kyHb0pwhLlypnE+peUxxS8r6L3U=", "dev": true, "dependencies": { - "repeating": "^2.0.0" + "html-comment-regex": "^1.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/indexes-of": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", - "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", - "dev": true - }, - "node_modules/indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "node_modules/is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha1-oFX2rlcZLK7jKeeoYBGLSXqVDzg=", "dev": true, "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "has-symbols": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w=", + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, - "node_modules/ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc=", - "deprecated": "Please update to ini >=1.3.6 to avoid a prototype pollution issue", - "dev": true, - "engines": { - "node": "*" - } + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true }, - "node_modules/inquirer": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha1-ndLyrXZdyrH/BEO0kUQqILoifck=", + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0=", "dev": true, - "dependencies": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^2.0.4", - "figures": "^2.0.0", - "lodash": "^4.3.0", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rx-lite": "^4.0.8", - "rx-lite-aggregates": "^4.0.8", - "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", - "through": "^2.3.6" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/inquirer/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "node_modules/is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", "dev": true, "engines": { "node": ">=4" } }, - "node_modules/inquirer/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "node_modules/is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha1-1QLTOCWQ6jAEiTdGdUyJE5lz4jI=", + "dev": true + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/isbinaryfile": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.2.tgz", + "integrity": "sha1-v8RWQtpkVoHGEMyoMQIuMK9CZIg=", "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, "engines": { - "node": ">=4" + "node": ">= 8.0.0" } }, - "node_modules/internal-ip": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", - "integrity": "sha1-hFRSuq2dLKO2nGNaE3rLmg2tCQc=", + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true, - "dependencies": { - "default-gateway": "^4.2.0", - "ipaddr.js": "^1.9.0" - }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/internal-ip/node_modules/default-gateway": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", - "integrity": "sha1-FnEEx1AMIRX23WmwpTa7jtcgVSs=", + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "node_modules/javascript-stringify": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-1.6.0.tgz", + "integrity": "sha1-FC0RHzpuPa6PSpr9d9RYVbWpzOM=", + "dev": true + }, + "node_modules/js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha1-xs7ljrNVA3LfjeuF+tXOZs4B1Z0=", "dev": true, - "dependencies": { - "execa": "^1.0.0", - "ip-regex": "^2.1.0" - }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha1-YQ88ksk1nOHbYW5TgAjSP/NRWOY=", + "node_modules/js-message": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.5.tgz", + "integrity": "sha1-IwDSSxrwjondCVvBpMnJz8uJLRU=", "dev": true, - "dependencies": { - "loose-envify": "^1.0.0" + "engines": { + "node": ">=0.6.0" } }, - "node_modules/invert-kv": { + "node_modules/js-queue": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha1-c5P1r6Weyf9fZ6J2INEcIm4+7AI=", + "resolved": "https://registry.npmjs.org/js-queue/-/js-queue-2.0.0.tgz", + "integrity": "sha1-NiITz4YPRo8BJfxslqvBdCUx+Ug=", "dev": true, + "dependencies": { + "easy-stack": "^1.0.0" + }, "engines": { - "node": ">=4" + "node": ">=1.0.0" } }, - "node_modules/ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha1-GSA/tZmR35jjoocFDUZHzerzJJk=", "dev": true }, - "node_modules/ip-regex": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", - "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "node_modules/js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha1-r/FRswv9+o5J4F2iLnQV6d+jeEc=", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha1-gFZNLkg9rPbo7yCWUKZ98/DCg6Q=", "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, "engines": { "node": ">=4" } }, - "node_modules/ipaddr.js": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", - "integrity": "sha1-N9905DCg5HVQ/lSi3v4w2KzZX2U=", + "node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha1-u4Z8+zRQ5pEHwTHRxRS6s9yLyqk=", + "dev": true + }, + "node_modules/json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA=", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "node_modules/json3": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", + "integrity": "sha1-f8EON1/FrkLEcFpcwKpvYr4wW4E=", + "dev": true + }, + "node_modules/json5": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", + "integrity": "sha1-56DGLEgoXGKNIKELhcibuAfDKFA=", "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + }, "engines": { - "node": ">= 0.10" + "node": ">=6" } }, - "node_modules/is-absolute-url": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", - "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", "dev": true, "engines": { - "node": ">=0.10.0" + "node": "*" } }, - "node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "node_modules/jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", "dev": true, + "engines": [ + "node >=0.6.0" + ], "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" } }, - "node_modules/is-accessor-descriptor/node_modules/kind-of": { + "node_modules/jszip": { "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.2.2.tgz", + "integrity": "sha1-sUOBbffhBqlZepTHdJM4WtylvR0=", "dev": true, "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "set-immediate-shim": "~1.0.1" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "node_modules/keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha1-7MIoSG9pmR5J6UdkhaW+Ho/FxNk=", "dev": true, "dependencies": { - "binary-extensions": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" + "json-buffer": "3.0.0" } }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", + "node_modules/killable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", + "integrity": "sha1-TIzkQRh6Bhx0dPuHygjipjgZSJI=", "dev": true }, - "node_modules/is-callable": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha1-HhrfIZ4e62hNaR+dagX/DTCiTXU=", + "node_modules/kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=", "dev": true, "engines": { - "node": ">= 0.4" + "node": ">=0.10.0" } }, - "node_modules/is-ci": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", - "integrity": "sha1-43ecjuF/zPQoSI9uKBGH8uYyhBw=", + "node_modules/latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha1-EZ3+kI/jjRXfpD7NE/oS7Igy+s4=", "dev": true, "dependencies": { - "ci-info": "^1.5.0" + "package-json": "^6.3.0" }, - "bin": { - "is-ci": "bin.js" + "engines": { + "node": ">=8" } }, - "node_modules/is-color-stop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", - "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=", + "node_modules/launch-editor": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.2.1.tgz", + "integrity": "sha1-hxtaPuOdZoD8wm03kwtu7aidsMo=", "dev": true, "dependencies": { - "css-color-names": "^0.0.4", - "hex-color-regex": "^1.1.0", - "hsl-regex": "^1.0.0", - "hsla-regex": "^1.0.0", - "rgb-regex": "^1.0.1", - "rgba-regex": "^1.0.0" + "chalk": "^2.3.0", + "shell-quote": "^1.6.1" } }, - "node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "node_modules/launch-editor-middleware": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/launch-editor-middleware/-/launch-editor-middleware-2.2.1.tgz", + "integrity": "sha1-4UsH5scVSwpLhqD9NFeE5FgEwVc=", "dev": true, "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" + "launch-editor": "^2.2.1" } }, - "node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "node_modules/lazy-val": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.4.tgz", + "integrity": "sha1-iCY2pyRcLP5uCk47psXWihN+XGU=", + "dev": true + }, + "node_modules/lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", "dev": true, "dependencies": { - "is-buffer": "^1.1.5" + "readable-stream": "^2.0.5" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.6.3" } }, - "node_modules/is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "node_modules/lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha1-bvXS32DlL4LrIopMNz6NHzlyU88=", "dev": true, + "dependencies": { + "invert-kv": "^2.0.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=6" } }, - "node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8.0" } }, - "node_modules/is-descriptor/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha1-3Pgt7lRfRgdNryAMfBxaCOD0D2o=", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "immediate": "~3.0.5" } }, - "node_modules/is-directory": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "node_modules/load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "node_modules/load-json-file/node_modules/parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "dependencies": { - "number-is-nan": "^1.0.0" + "error-ex": "^1.2.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha1-dWfb6fL14kZ7x3q4PEopSCQHpdw=", + "node_modules/load-json-file/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, "engines": { "node": ">=0.10.0" } }, - "node_modules/is-installed-globally": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", - "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "node_modules/loader-fs-cache": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/loader-fs-cache/-/loader-fs-cache-1.0.2.tgz", + "integrity": "sha1-VM7fa3J+F3n9jwEgXwX26IcG8IY=", "dev": true, "dependencies": { - "global-dirs": "^0.1.0", - "is-path-inside": "^1.0.0" - }, - "engines": { - "node": ">=4" + "find-cache-dir": "^0.1.1", + "mkdirp": "0.5.1" } }, - "node_modules/is-installed-globally/node_modules/is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "node_modules/loader-fs-cache/node_modules/find-cache-dir": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz", + "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=", "dev": true, "dependencies": { - "path-is-inside": "^1.0.1" + "commondir": "^1.0.1", + "mkdirp": "^0.5.1", + "pkg-dir": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/is-npm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-3.0.0.tgz", - "integrity": "sha1-7JFHv7YpxD9JTPZ5Nqlh7ex+gFM=", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "node_modules/loader-fs-cache/node_modules/find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, "dependencies": { - "kind-of": "^3.0.2" + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "node_modules/loader-fs-cache/node_modules/path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, "dependencies": { - "is-buffer": "^1.1.5" + "pinkie-promise": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "node_modules/loader-fs-cache/node_modules/pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", "dev": true, + "dependencies": { + "find-up": "^1.0.0" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha1-Z9Q7gmZKe1GR/ZEZEn6zAASKn9s=", + "node_modules/loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha1-7UcGa/5TTX6ExMe5mYwqdWB9k1c=", "dev": true, "engines": { - "node": ">=6" + "node": ">=4.3.0 <5.0.0 || >=5.10" } }, - "node_modules/is-path-in-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", - "integrity": "sha1-v+Lcomxp85cmWkAJljYCk1oFOss=", + "node_modules/loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha1-H/XcaRHJ8KBiUxpMBLYJQGEIwsc=", "dev": true, "dependencies": { - "is-path-inside": "^2.1.0" + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" }, "engines": { - "node": ">=6" + "node": ">=4.0.0" } }, - "node_modules/is-path-inside": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha1-fJgQWH1lmkDSe8201WFuqwWUlLI=", + "node_modules/loader-utils/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha1-d5+wAYYE+oVOrL9iUhgNg1Q+Pb4=", "dev": true, "dependencies": { - "path-is-inside": "^1.0.2" + "minimist": "^1.2.0" }, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true, - "engines": { - "node": ">=0.10.0" + "bin": { + "json5": "lib/cli.js" } }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", + "node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, "dependencies": { - "isobject": "^3.0.1" + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/is-port-reachable": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-port-reachable/-/is-port-reachable-4.0.0.tgz", - "integrity": "sha512-9UoipoxYmSk6Xy7QFgRv2HDyaysmgSG75TFQs6S+3pDM7ZhKTF/bskZV+0UlABHzKjNVhPjYCLfeZUEg1wXxig==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "node_modules/lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha1-tEf2ZwoEVbv+7dETku/zMOoJdUg=", + "dev": true }, - "node_modules/is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "node_modules/lodash.defaultsdeep": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz", + "integrity": "sha1-US6b1yHSctlOPTpjZT+hdRZ0HKY=", "dev": true }, - "node_modules/is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true, - "dependencies": { - "has": "^1.0.1" + "node_modules/lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha1-hImxyw0p/4gZXM7KRI/21swpXDY=", + "dev": true + }, + "node_modules/lodash.mapvalues": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", + "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=", + "dev": true + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha1-VYqlO0O2YeGSWgr9+japoQhf5Xo=", + "dev": true + }, + "node_modules/lodash.transform": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.transform/-/lodash.transform-4.6.0.tgz", + "integrity": "sha1-EjBkIvYzJK7YSD0/ODMrX2cFR6A=", + "dev": true + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, + "node_modules/log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha1-V0Dhxdbw39pK2TI7UzIQfva0xAo=", + "dev": true, + "dependencies": { + "chalk": "^2.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=4" } }, - "node_modules/is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha1-+xj4fOH+uSUWnJpAfBkxijIG7Yg=", - "dev": true - }, - "node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "node_modules/loglevel": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.3.tgz", + "integrity": "sha1-d/LrZL5VpATJ/QStFtV8HW1rEoA=", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 0.6.0" } }, - "node_modules/is-svg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz", - "integrity": "sha1-kyHb0pwhLlypnE+peUxxS8r6L3U=", + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha1-ce5R+nvkyuwaY4OffmgtgTLTDK8=", "dev": true, "dependencies": { - "html-comment-regex": "^1.1.0" + "js-tokens": "^3.0.0 || ^4.0.0" }, - "engines": { - "node": ">=4" + "bin": { + "loose-envify": "cli.js" } }, - "node_modules/is-symbol": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", - "integrity": "sha1-oFX2rlcZLK7jKeeoYBGLSXqVDzg=", + "node_modules/loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", "dev": true, "dependencies": { - "has-symbols": "^1.0.0" + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=0.10.0" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "node_modules/lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", "dev": true }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0=", + "node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha1-b54wtHCE2XGnyCD/FabFFnt0wm8=", "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha1-HaJ+ZxAnGUdpXa9oSOhH8B2EuSA=", "dev": true, - "engines": { - "node": ">=4" + "dependencies": { + "yallist": "^3.0.2" } }, - "node_modules/is-yarn-global": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", - "integrity": "sha1-1QLTOCWQ6jAEiTdGdUyJE5lz4jI=", - "dev": true - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/isbinaryfile": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.2.tgz", - "integrity": "sha1-v8RWQtpkVoHGEMyoMQIuMK9CZIg=", + "node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha1-XwMQ4YuL6JjMBwCSlaMK5B6R5vU=", "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, "engines": { - "node": ">= 8.0.0" + "node": ">=6" } }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "node_modules/map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha1-fVg6cwZDTAVf5HSw9FB45uG0uSo=", "dev": true, + "dependencies": { + "p-defer": "^1.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "node_modules/javascript-stringify": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-1.6.0.tgz", - "integrity": "sha1-FC0RHzpuPa6PSpr9d9RYVbWpzOM=", - "dev": true - }, - "node_modules/js-levenshtein": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", - "integrity": "sha1-xs7ljrNVA3LfjeuF+tXOZs4B1Z0=", + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/js-message": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.5.tgz", - "integrity": "sha1-IwDSSxrwjondCVvBpMnJz8uJLRU=", + "node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", "dev": true, "engines": { - "node": ">=0.6.0" + "node": ">=0.10.0" } }, - "node_modules/js-queue": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/js-queue/-/js-queue-2.0.0.tgz", - "integrity": "sha1-NiITz4YPRo8BJfxslqvBdCUx+Ug=", + "node_modules/map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", "dev": true, "dependencies": { - "easy-stack": "^1.0.0" + "object-visit": "^1.0.0" }, "engines": { - "node": ">=1.0.0" + "node": ">=0.10.0" } }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha1-GSA/tZmR35jjoocFDUZHzerzJJk=", - "dev": true - }, - "node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha1-r/FRswv9+o5J4F2iLnQV6d+jeEc=", + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha1-tdB7jjIW4+J81yjXL3DR5qNCAF8=", "dev": true, "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" } }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "node_modules/mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha1-aZs8OKxvHXKAkaZGULZdOIUC/Vs=", "dev": true }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha1-gFZNLkg9rPbo7yCWUKZ98/DCg6Q=", + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, "engines": { - "node": ">=4" + "node": ">= 0.6" } }, - "node_modules/json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha1-u4Z8+zRQ5pEHwTHRxRS6s9yLyqk=", - "dev": true - }, - "node_modules/json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA=", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "node_modules/json3": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", - "integrity": "sha1-f8EON1/FrkLEcFpcwKpvYr4wW4E=", - "dev": true - }, - "node_modules/json5": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", - "integrity": "sha1-56DGLEgoXGKNIKELhcibuAfDKFA=", + "node_modules/mem": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha1-Rhr0l7xK4JYIzbLmDu+2m/90QXg=", "dev": true, "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" }, "engines": { "node": ">=6" } }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "node_modules/mem/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha1-ftLCzMyvhNP/y3pptXcR/CCDQBs=", "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "engines": { + "node": ">=6" } }, - "node_modules/jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "node_modules/memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", "dev": true, - "engines": { - "node": "*" + "dependencies": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" } }, - "node_modules/jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "node_modules/meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, - "engines": [ - "node >=0.6.0" - ], "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/jszip": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.2.2.tgz", - "integrity": "sha1-sUOBbffhBqlZepTHdJM4WtylvR0=", + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "node_modules/merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha1-L93n5gIJOfcJBqaPLXrmheTIxkY=", "dev": true, "dependencies": { - "lie": "~3.3.0", - "pako": "~1.0.2", - "readable-stream": "~2.3.6", - "set-immediate-shim": "~1.0.1" + "source-map": "^0.6.1" } }, - "node_modules/keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha1-7MIoSG9pmR5J6UdkhaW+Ho/FxNk=", + "node_modules/merge-source-map/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true, - "dependencies": { - "json-buffer": "3.0.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/killable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", - "integrity": "sha1-TIzkQRh6Bhx0dPuHygjipjgZSJI=", + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, - "node_modules/kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=", + "node_modules/merge2": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.3.tgz", + "integrity": "sha1-fumdvWm7ZIFoklPwGEiKG5ArDtU=", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 4.5.0" } }, - "node_modules/latest-version": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", - "integrity": "sha1-EZ3+kI/jjRXfpD7NE/oS7Igy+s4=", + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", "dev": true, - "dependencies": { - "package-json": "^6.3.0" - }, "engines": { - "node": ">=8" + "node": ">= 0.6" } }, - "node_modules/launch-editor": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.2.1.tgz", - "integrity": "sha1-hxtaPuOdZoD8wm03kwtu7aidsMo=", + "node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=", "dev": true, "dependencies": { - "chalk": "^2.3.0", - "shell-quote": "^1.6.1" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/launch-editor-middleware": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/launch-editor-middleware/-/launch-editor-middleware-2.2.1.tgz", - "integrity": "sha1-4UsH5scVSwpLhqD9NFeE5FgEwVc=", + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha1-8IA1HIZbDcViqEYpZtqlNUPHik0=", "dev": true, "dependencies": { - "launch-editor": "^2.2.1" + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" } }, - "node_modules/lazy-val": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.4.tgz", - "integrity": "sha1-iCY2pyRcLP5uCk47psXWihN+XGU=", - "dev": true - }, - "node_modules/lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "node_modules/mime": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", + "integrity": "sha1-vXuRE1/GsBzePpuuM9ZZtj2IV+U=", "dev": true, - "dependencies": { - "readable-stream": "^2.0.5" + "bin": { + "mime": "cli.js" }, "engines": { - "node": ">= 0.6.3" + "node": ">=4.0.0" } }, - "node_modules/lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha1-bvXS32DlL4LrIopMNz6NHzlyU88=", - "dev": true, - "dependencies": { - "invert-kv": "^2.0.0" - }, + "node_modules/mime-db": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha1-plBX6ZjbCQ9zKmj2wnbTh9QSbDI=", "engines": { - "node": ">=6" + "node": ">= 0.6" } }, - "node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, + "node_modules/mime-types": { + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha1-tvjQs+lR77d97eyhlM/20W9nb4E=", "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "mime-db": "1.40.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 0.6" } }, - "node_modules/lie": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", - "integrity": "sha1-3Pgt7lRfRgdNryAMfBxaCOD0D2o=", + "node_modules/mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI=", "dev": true, - "dependencies": { - "immediate": "~3.0.5" + "engines": { + "node": ">=4" } }, - "node_modules/lines-and-columns": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", - "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", - "dev": true - }, - "node_modules/load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha1-SSNTiHju9CBjy4o+OweYeBSHqxs=", "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/load-json-file/node_modules/parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "node_modules/mini-css-extract-plugin": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.6.0.tgz", + "integrity": "sha1-o/Ezctb83pEvPuTNA5ZlcEgB47k=", "dev": true, "dependencies": { - "error-ex": "^1.2.0" + "loader-utils": "^1.1.0", + "normalize-url": "^2.0.1", + "schema-utils": "^1.0.0", + "webpack-sources": "^1.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^4.4.0" } }, - "node_modules/load-json-file/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "node_modules/mini-css-extract-plugin/node_modules/normalize-url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", + "integrity": "sha1-g1qdoVUfom9w6SMpBpojqmV01+Y=", "dev": true, + "dependencies": { + "prepend-http": "^2.0.0", + "query-string": "^5.0.1", + "sort-keys": "^2.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/loader-fs-cache": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/loader-fs-cache/-/loader-fs-cache-1.0.2.tgz", - "integrity": "sha1-VM7fa3J+F3n9jwEgXwX26IcG8IY=", + "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", "dev": true, "dependencies": { - "find-cache-dir": "^0.1.1", - "mkdirp": "0.5.1" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" } }, - "node_modules/loader-fs-cache/node_modules/find-cache-dir": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz", - "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=", + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha1-LhlN4ERibUoQ5/f7wAznPoPk1cc=", + "dev": true + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", "dev": true, "dependencies": { - "commondir": "^1.0.1", - "mkdirp": "^0.5.1", - "pkg-dir": "^1.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=0.10.0" + "node": "*" } }, - "node_modules/loader-fs-cache/node_modules/find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "node_modules/minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "node_modules/mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha1-6goykfl+C16HdrNj1fChLZTGcCI=", "dev": true, "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=4.0.0" } }, - "node_modules/loader-fs-cache/node_modules/path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "node_modules/mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha1-ESC0PcNZp4Xc5ltVuC4lfM9HlWY=", "dev": true, "dependencies": { - "pinkie-promise": "^2.0.0" + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/loader-fs-cache/node_modules/pkg-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", - "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "node_modules/mixin-deep/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", "dev": true, "dependencies": { - "find-up": "^1.0.0" + "is-plain-object": "^2.0.4" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/loader-runner": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", - "integrity": "sha1-7UcGa/5TTX6ExMe5mYwqdWB9k1c=", - "dev": true, - "engines": { - "node": ">=4.3.0 <5.0.0 || >=5.10" - } - }, - "node_modules/loader-utils": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", - "integrity": "sha1-H/XcaRHJ8KBiUxpMBLYJQGEIwsc=", + "node_modules/mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", "dev": true, "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^2.0.0", - "json5": "^1.0.1" + "minimist": "0.0.8" }, - "engines": { - "node": ">=4.0.0" + "bin": { + "mkdirp": "bin/cmd.js" } }, - "node_modules/loader-utils/node_modules/json5": { + "node_modules/mkdirp/node_modules/minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "node_modules/move-concurrently": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha1-d5+wAYYE+oVOrL9iUhgNg1Q+Pb4=", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", "dev": true, "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" } }, - "node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=" + }, + "node_modules/multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha1-oOx72QVcQoL3kMPIL04o2zsxsik=", "dev": true, "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" }, - "engines": { - "node": ">=4" + "bin": { + "multicast-dns": "cli.js" } }, - "node_modules/lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha1-tEf2ZwoEVbv+7dETku/zMOoJdUg=", - "dev": true - }, - "node_modules/lodash.defaultsdeep": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz", - "integrity": "sha1-US6b1yHSctlOPTpjZT+hdRZ0HKY=", + "node_modules/multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", "dev": true }, - "node_modules/lodash.kebabcase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", - "integrity": "sha1-hImxyw0p/4gZXM7KRI/21swpXDY=", + "node_modules/mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, - "node_modules/lodash.mapvalues": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", - "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=", - "dev": true + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha1-lQCAV6Vsr63CvGPd5/n/aVWUjjI=", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true + "node_modules/nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha1-uHqKpPwN6P5r6IiVs4mD/yZb0Rk=", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha1-VYqlO0O2YeGSWgr9+japoQhf5Xo=", + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, - "node_modules/lodash.transform": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.transform/-/lodash.transform-4.6.0.tgz", - "integrity": "sha1-EjBkIvYzJK7YSD0/ODMrX2cFR6A=", + "node_modules/negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha1-/qz3zPUlp3rpY0Q2pkiD/+yjRvs=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", + "integrity": "sha1-rCetpmFn+ohJpq3dg39rGJrSCBw=", "dev": true }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y=", "dev": true }, - "node_modules/log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha1-V0Dhxdbw39pK2TI7UzIQfva0xAo=", + "node_modules/no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha1-YLgTOWvjmz8SiKTB7V0efSi0ZKw=", "dev": true, "dependencies": { - "chalk": "^2.0.1" - }, - "engines": { - "node": ">=4" + "lower-case": "^1.1.1" } }, - "node_modules/loglevel": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.3.tgz", - "integrity": "sha1-d/LrZL5VpATJ/QStFtV8HW1rEoA=", + "node_modules/node-forge": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", + "integrity": "sha1-bBUsNFzhHFL0ZcKr2VfoY5zWdN8=", "dev": true, "engines": { - "node": ">= 0.6.0" + "node": "*" } }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha1-ce5R+nvkyuwaY4OffmgtgTLTDK8=", + "node_modules/node-ipc": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/node-ipc/-/node-ipc-9.1.1.tgz", + "integrity": "sha1-TiRe1pOOZRAOWV68XcNLFujdXWk=", "dev": true, "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" + "event-pubsub": "4.3.0", + "js-message": "1.0.5", + "js-queue": "2.0.0" }, - "bin": { - "loose-envify": "cli.js" + "engines": { + "node": ">=4.0.0" } }, - "node_modules/loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "node_modules/node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha1-tk9RPRgzhiX5A0bSew0jXmMfZCU=", "dev": true, "dependencies": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" } }, - "node_modules/lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", + "node_modules/node-libs-browser/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true }, - "node_modules/lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha1-b54wtHCE2XGnyCD/FabFFnt0wm8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha1-HaJ+ZxAnGUdpXa9oSOhH8B2EuSA=", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true }, - "node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha1-XwMQ4YuL6JjMBwCSlaMK5B6R5vU=", + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha1-5m2xg4sgDB38IzIl0SyzZSDiNKg=", "dev": true, "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, - "node_modules/map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha1-fVg6cwZDTAVf5HSw9FB45uG0uSo=", + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU=", "dev": true, - "dependencies": { - "p-defer": "^1.0.0" - }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "node_modules/normalize-url": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", + "integrity": "sha1-suHE3E98bVd0PfczpPWXjRhlBVk=", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "node_modules/npm-install-package": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/npm-install-package/-/npm-install-package-2.1.0.tgz", + "integrity": "sha1-1+/jz816sAYUuJbqUxGdyaslkSU=", + "dev": true + }, + "node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "dependencies": { - "object-visit": "^1.0.0" + "path-key": "^2.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha1-tdB7jjIW4+J81yjXL3DR5qNCAF8=", + "node_modules/nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha1-sr0pXDfj3VijvwcAN2Zjuk2c8Fw=", "dev": true, "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" + "boolbase": "~1.0.0" } }, - "node_modules/mdn-data": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", - "integrity": "sha1-aZs8OKxvHXKAkaZGULZdOIUC/Vs=", - "dev": true - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "node_modules/nugget": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nugget/-/nugget-2.0.1.tgz", + "integrity": "sha1-IBCVpIfhrTYIGzQy+jytpPjQcbA=", "dev": true, - "engines": { - "node": ">= 0.6" + "dependencies": { + "debug": "^2.1.3", + "minimist": "^1.1.0", + "pretty-bytes": "^1.0.2", + "progress-stream": "^1.1.0", + "request": "^2.45.0", + "single-line-log": "^1.1.2", + "throttleit": "0.0.2" + }, + "bin": { + "nugget": "bin.js" } }, - "node_modules/mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha1-Rhr0l7xK4JYIzbLmDu+2m/90QXg=", + "node_modules/nugget/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "dependencies": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - }, - "engines": { - "node": ">=6" + "ms": "2.0.0" } }, - "node_modules/mem/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha1-ftLCzMyvhNP/y3pptXcR/CCDQBs=", + "node_modules/nugget/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha1-R6ewFrqmi1+g7PPe4IqFxnmsZFU=", "dev": true, - "dependencies": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" + "engines": { + "node": "*" } }, - "node_modules/meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=" + }, + "node_modules/object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, "dependencies": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "node_modules/merge-source-map": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", - "integrity": "sha1-L93n5gIJOfcJBqaPLXrmheTIxkY=", + "node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "dependencies": { - "source-map": "^0.6.1" + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/merge-source-map/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.3.tgz", - "integrity": "sha1-fumdvWm7ZIFoklPwGEiKG5ArDtU=", + "node_modules/object-hash": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.3.1.tgz", + "integrity": "sha1-/eRSCYqVHLFF8Dm7fUVUSd3BJt8=", "dev": true, "engines": { - "node": ">= 4.5.0" + "node": ">= 0.10.0" } }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha1-HEfyct8nfzsdrwYWd9nILiMixg4=", "dev": true, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" } }, - "node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=", + "node_modules/object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "dev": true, "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "isobject": "^3.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha1-8IA1HIZbDcViqEYpZtqlNUPHik0=", + "node_modules/object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha1-lovxEA15Vrs8oIbwBvhGs7xACNo=", "dev": true, "dependencies": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" }, - "bin": { - "miller-rabin": "bin/miller-rabin" + "engines": { + "node": ">= 0.4" } }, - "node_modules/mime": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", - "integrity": "sha1-vXuRE1/GsBzePpuuM9ZZtj2IV+U=", + "node_modules/object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", "dev": true, - "bin": { - "mime": "cli.js" + "dependencies": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" }, "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha1-plBX6ZjbCQ9zKmj2wnbTh9QSbDI=", - "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, - "node_modules/mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha1-tvjQs+lR77d97eyhlM/20W9nb4E=", + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, "dependencies": { - "mime-db": "1.40.0" + "isobject": "^3.0.1" }, "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } }, - "node_modules/mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI=", + "node_modules/object.values": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", + "integrity": "sha1-v2gQ712j5TJXkOqqK+IT6oRiTak=", "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + }, "engines": { - "node": ">=4" + "node": ">= 0.4" } }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha1-SSNTiHju9CBjy4o+OweYeBSHqxs=", - "dev": true, - "engines": { - "node": ">=4" - } + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha1-Cb6jND1BhZ69RGKS0RydTbYZCE4=", + "dev": true }, - "node_modules/mini-css-extract-plugin": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.6.0.tgz", - "integrity": "sha1-o/Ezctb83pEvPuTNA5ZlcEgB47k=", + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", "dev": true, "dependencies": { - "loader-utils": "^1.1.0", - "normalize-url": "^2.0.1", - "schema-utils": "^1.0.0", - "webpack-sources": "^1.1.0" + "ee-first": "1.1.1" }, "engines": { - "node": ">= 6.9.0" - }, - "peerDependencies": { - "webpack": "^4.4.0" + "node": ">= 0.8" } }, - "node_modules/mini-css-extract-plugin/node_modules/normalize-url": { + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha1-dysK5qqlJcOZ5Imt+tkMQD6zwo8=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", - "integrity": "sha1-g1qdoVUfom9w6SMpBpojqmV01+Y=", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, "dependencies": { - "prepend-http": "^2.0.0", - "query-string": "^5.0.1", - "sort-keys": "^2.0.0" + "mimic-fn": "^1.0.0" }, "engines": { "node": ">=4" } }, - "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", + "node_modules/open": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz", + "integrity": "sha1-XBPpbQ3IlGhhZPGJZez+iJ7PyKk=", "dev": true, "dependencies": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" + "is-wsl": "^1.1.0" }, "engines": { - "node": ">= 4" + "node": ">=8" } }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha1-LhlN4ERibUoQ5/f7wAznPoPk1cc=", - "dev": true - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true + "node_modules/opener": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz", + "integrity": "sha1-bS8Od/GgrwAyrKcWwsH7uOfoq+0=", + "dev": true, + "bin": { + "opener": "bin/opener-bin.js" + } }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "node_modules/opn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha1-/HFk+rVtI1kExRw7J9pnWMo7m/w=", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "is-wsl": "^1.1.0" }, "engines": { - "node": "*" + "node": ">=4" } }, - "node_modules/minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "node_modules/optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "dependencies": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + } + }, + "node_modules/optimist/node_modules/minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true }, - "node_modules/mississippi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha1-6goykfl+C16HdrNj1fChLZTGcCI=", + "node_modules/optimist/node_modules/wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", "dev": true, - "dependencies": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - }, "engines": { - "node": ">=4.0.0" + "node": ">=0.4.0" } }, - "node_modules/mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha1-ESC0PcNZp4Xc5ltVuC4lfM9HlWY=", + "node_modules/optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "dev": true, "dependencies": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8.0" } }, - "node_modules/mixin-deep/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", + "node_modules/ora": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz", + "integrity": "sha1-vwdSSRBZo+8+1MhQl1Md6f280xg=", "dev": true, "dependencies": { - "is-plain-object": "^2.0.4" + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-spinners": "^2.0.0", + "log-symbols": "^2.2.0", + "strip-ansi": "^5.2.0", + "wcwidth": "^1.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "node_modules/original": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", + "integrity": "sha1-5EKmHP/hxf0gpl8yYcJmY7MD8l8=", "dev": true, "dependencies": { - "minimist": "0.0.8" - }, - "bin": { - "mkdirp": "bin/cmd.js" + "url-parse": "^1.4.3" } }, - "node_modules/mkdirp/node_modules/minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "node_modules/os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", "dev": true }, - "node_modules/move-concurrently": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "node_modules/os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha1-qAKm7hfyTBBIOrmTVxnO9O0Wvxo=", "dev": true, "dependencies": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=" - }, - "node_modules/multicast-dns": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", - "integrity": "sha1-oOx72QVcQoL3kMPIL04o2zsxsik=", + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, - "dependencies": { - "dns-packet": "^1.3.1", - "thunky": "^1.0.2" - }, - "bin": { - "multicast-dns": "cli.js" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/multicast-dns-service-types": { + "node_modules/p-cancelable": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", - "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", - "dev": true - }, - "node_modules/mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha1-lQCAV6Vsr63CvGPd5/n/aVWUjjI=", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha1-0HjRWjr0CSIMiG8dmgyi5EGrJsw=", "dev": true, - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true, - "optional": true - }, - "node_modules/nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha1-uHqKpPwN6P5r6IiVs4mD/yZb0Rk=", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "node_modules/negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha1-/qz3zPUlp3rpY0Q2pkiD/+yjRvs=", + "node_modules/p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true, "engines": { - "node": ">= 0.6" + "node": ">=4" } }, - "node_modules/neo-async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", - "integrity": "sha1-rCetpmFn+ohJpq3dg39rGJrSCBw=", - "dev": true - }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y=", - "dev": true - }, - "node_modules/no-case": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha1-YLgTOWvjmz8SiKTB7V0efSi0ZKw=", + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true, - "dependencies": { - "lower-case": "^1.1.1" + "engines": { + "node": ">=4" } }, - "node_modules/node-forge": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", - "integrity": "sha1-bBUsNFzhHFL0ZcKr2VfoY5zWdN8=", + "node_modules/p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha1-kYzrrqJIpiz3/6uOO8qMX4gvxC4=", "dev": true, "engines": { - "node": "*" + "node": ">=6" } }, - "node_modules/node-ipc": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/node-ipc/-/node-ipc-9.1.1.tgz", - "integrity": "sha1-TiRe1pOOZRAOWV68XcNLFujdXWk=", + "node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha1-uGvV8MJWkJEcdZD8v8IBDVSzzLg=", "dev": true, "dependencies": { - "event-pubsub": "4.3.0", - "js-message": "1.0.5", - "js-queue": "2.0.0" + "p-try": "^1.0.0" }, "engines": { - "node": ">=4.0.0" + "node": ">=4" } }, - "node_modules/node-libs-browser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", - "integrity": "sha1-tk9RPRgzhiX5A0bSew0jXmMfZCU=", + "node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "dependencies": { - "assert": "^1.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^3.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "0.0.1", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.11.0", - "vm-browserify": "^1.0.1" + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/node-libs-browser/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "node_modules/node-releases": { - "version": "1.1.26", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.26.tgz", - "integrity": "sha1-8wVj7cXH3CDPUkzIZS/6e+B2KTc=", + "node_modules/p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha1-MQko/u+cnsxltosXaTAYpmXOoXU=", "dev": true, - "dependencies": { - "semver": "^5.3.0" + "engines": { + "node": ">=6" } }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha1-5m2xg4sgDB38IzIl0SyzZSDiNKg=", + "node_modules/p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha1-MWtMiJPiyNwc+okfQGxLQivr8yg=", "dev": true, "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "retry": "^0.12.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU=", + "node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "node_modules/package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha1-b+7ayjXnVyWHbQsOZJdGl/7RRbA=", "dev": true, + "dependencies": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/normalize-url": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", - "integrity": "sha1-suHE3E98bVd0PfczpPWXjRhlBVk=", + "node_modules/package-json/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=", "dev": true, - "engines": { - "node": ">=6" + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/npm-install-package": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/npm-install-package/-/npm-install-package-2.1.0.tgz", - "integrity": "sha1-1+/jz816sAYUuJbqUxGdyaslkSU=", + "node_modules/pako": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", + "integrity": "sha1-Qyi621CGpCaqkPVBl31JVdpclzI=", "dev": true }, - "node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "node_modules/parallel-transform": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", "dev": true, "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" + "cyclist": "~0.2.2", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" } }, - "node_modules/nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha1-sr0pXDfj3VijvwcAN2Zjuk2c8Fw=", + "node_modules/param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", "dev": true, "dependencies": { - "boolbase": "~1.0.0" + "no-case": "^2.2.0" } }, - "node_modules/nugget": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nugget/-/nugget-2.0.1.tgz", - "integrity": "sha1-IBCVpIfhrTYIGzQy+jytpPjQcbA=", + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha1-aR0nCeeMefrjoVZiJFLQB2LKqqI=", "dev": true, "dependencies": { - "debug": "^2.1.3", - "minimist": "^1.1.0", - "pretty-bytes": "^1.0.2", - "progress-stream": "^1.1.0", - "request": "^2.45.0", - "single-line-log": "^1.1.2", - "throttleit": "0.0.2" + "callsites": "^3.0.0" }, - "bin": { - "nugget": "bin.js" + "engines": { + "node": ">=6" } }, - "node_modules/nugget/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/nugget/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/num2fraction": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", - "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", - "dev": true - }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "node_modules/parent-module/node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha1-s2MKvYlDQy9Us/BRkjjjPNffL3M=", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha1-R6ewFrqmi1+g7PPe4IqFxnmsZFU=", + "node_modules/parse-asn1": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz", + "integrity": "sha1-N/Zij4I/vesic7TVQENKIvPvH8w=", "dev": true, - "engines": { - "node": "*" + "dependencies": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "engines": { - "node": ">=0.10.0" + "node_modules/parse-color": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-color/-/parse-color-1.0.0.tgz", + "integrity": "sha1-e3SLlag/A/FqlPU15S1/PZRlhhk=", + "dev": true, + "dependencies": { + "color-convert": "~0.5.0" } }, - "node_modules/object-component": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", - "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=" + "node_modules/parse-color/node_modules/color-convert": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", + "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=", + "dev": true }, - "node_modules/object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, "dependencies": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/object-copy/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, + "node_modules/parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha1-bXhlbj2o14tOwLkG98CO8d/j9gg=", + "dev": true + }, + "node_modules/parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" + "better-assert": "~1.0.0" } }, - "node_modules/object-copy/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, + "node_modules/parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", "dependencies": { - "is-buffer": "^1.1.5" - }, + "better-assert": "~1.0.0" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha1-naGee+6NEt/wUT7Vt2lXeTvC6NQ=", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, - "node_modules/object-hash": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.3.1.tgz", - "integrity": "sha1-/eRSCYqVHLFF8Dm7fUVUSd3BJt8=", + "node_modules/pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true, "engines": { - "node": ">= 0.10.0" + "node": ">=0.10.0" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha1-HEfyct8nfzsdrwYWd9nILiMixg4=", + "node_modules/path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha1-5sTd1+06onxoogzE5Q4aTug7vEo=", + "dev": true + }, + "node_modules/path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true, "engines": { - "node": ">= 0.4" + "node": ">=4" } }, - "node_modules/object-visit": { + "node_modules/path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, - "dependencies": { - "isobject": "^3.0.0" - }, "engines": { "node": ">=0.10.0" } }, - "node_modules/object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha1-lovxEA15Vrs8oIbwBvhGs7xACNo=", + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true, - "dependencies": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - }, "engines": { - "node": ">= 0.4" + "node": ">=4" } }, - "node_modules/object.getownpropertydescriptors": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", - "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "node_modules/path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha1-1i27VnlAXXLEc37FhgDp3c8G0kw=", + "dev": true + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha1-zvMdyOCho7sNEFwM2Xzzv0f0428=", "dev": true, "dependencies": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" + "pify": "^3.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">=4" } }, - "node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "node_modules/path-type/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/object.values": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", - "integrity": "sha1-v2gQ712j5TJXkOqqK+IT6oRiTak=", + "node_modules/pbkdf2": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", + "integrity": "sha1-l2wgZTBhexTrsyEUI597CTNuk6Y=", "dev": true, "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.12.0", - "function-bind": "^1.1.1", - "has": "^1.0.3" + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" }, "engines": { - "node": ">= 0.4" + "node": ">=0.12" } }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha1-Cb6jND1BhZ69RGKS0RydTbYZCE4=", + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", "dev": true }, - "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha1-dysK5qqlJcOZ5Imt+tkMQD6zwo8=", + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "dev": true + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha1-SyzSXFDVmHNcUCkiJP2MbfQeMjE=", "dev": true, "engines": { - "node": ">= 0.8" + "node": ">=6" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", "dev": true, - "dependencies": { - "wrappy": "1" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/onetime": { + "node_modules/pinkie-promise": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "dependencies": { - "mimic-fn": "^1.0.0" + "pinkie": "^2.0.0" }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/open": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz", - "integrity": "sha1-XBPpbQ3IlGhhZPGJZez+iJ7PyKk=", + "node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha1-J0kCDyOe2ZCIGx9xIQ1R62UjvqM=", "dev": true, "dependencies": { - "is-wsl": "^1.1.0" + "find-up": "^3.0.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/opener": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz", - "integrity": "sha1-bS8Od/GgrwAyrKcWwsH7uOfoq+0=", - "dev": true, - "bin": { - "opener": "bin/opener-bin.js" + "node": ">=6" } }, - "node_modules/opn": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", - "integrity": "sha1-/HFk+rVtI1kExRw7J9pnWMo7m/w=", + "node_modules/pkg-dir/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=", "dev": true, "dependencies": { - "is-wsl": "^1.1.0" + "locate-path": "^3.0.0" }, "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4=", "dev": true, "dependencies": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - } - }, - "node_modules/optimist/node_modules/minimist": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", - "dev": true - }, - "node_modules/optimist/node_modules/wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true, + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, "engines": { - "node": ">=0.4.0" + "node": ">=6" } }, - "node_modules/optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha1-QXyZQeYCepq8ulCS3SkE4lW1+8I=", "dev": true, "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" + "p-try": "^2.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=6" } }, - "node_modules/ora": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz", - "integrity": "sha1-vwdSSRBZo+8+1MhQl1Md6f280xg=", + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=", "dev": true, "dependencies": { - "chalk": "^2.4.2", - "cli-cursor": "^2.1.0", - "cli-spinners": "^2.0.0", - "log-symbols": "^2.2.0", - "strip-ansi": "^5.2.0", - "wcwidth": "^1.0.1" + "p-limit": "^2.0.0" }, "engines": { "node": ">=6" } }, - "node_modules/original": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", - "integrity": "sha1-5EKmHP/hxf0gpl8yYcJmY7MD8l8=", + "node_modules/pkg-dir/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha1-yyhoVA4xPWHeWPr741zpAE1VQOY=", "dev": true, - "dependencies": { - "url-parse": "^1.4.3" + "engines": { + "node": ">=6" } }, - "node_modules/os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true - }, - "node_modules/os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha1-qAKm7hfyTBBIOrmTVxnO9O0Wvxo=", + "node_modules/pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", + "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=", "dev": true, "dependencies": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" + "find-up": "^2.1.0" }, "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "node_modules/plist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.1.tgz", + "integrity": "sha1-qbkx0XwwTokS7wujvdYYK68uH4w=", "dev": true, + "dependencies": { + "base64-js": "^1.2.3", + "xmlbuilder": "^9.0.7", + "xmldom": "0.1.x" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha1-0HjRWjr0CSIMiG8dmgyi5EGrJsw=", + "node_modules/pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha1-KYuJ34uTsCIdv0Ia0rGx6iP8Z3c=", "dev": true, + "optional": true, "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "node_modules/pngparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pngparse/-/pngparse-2.0.1.tgz", + "integrity": "sha1-hoUt5N40n077HoUudSVlXlrF37g=" + }, + "node_modules/portfinder": { + "version": "1.0.21", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.21.tgz", + "integrity": "sha1-YOE5e5WsFwdJ23ADTs4wa5on4yQ=", "dev": true, + "dependencies": { + "async": "^1.5.2", + "debug": "^2.2.0", + "mkdirp": "0.5.x" + }, "engines": { - "node": ">=4" + "node": ">= 0.12.0" } }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "node_modules/portfinder/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, - "engines": { - "node": ">=4" + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/p-is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha1-kYzrrqJIpiz3/6uOO8qMX4gvxC4=", + "node_modules/portfinder/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", "dev": true, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha1-uGvV8MJWkJEcdZD8v8IBDVSzzLg=", + "node_modules/postcss": { + "version": "7.0.17", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz", + "integrity": "sha1-TaG9/1Mi1KCsqrTYfz54JDa60x8=", "dev": true, "dependencies": { - "p-try": "^1.0.0" + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" }, "engines": { - "node": ">=4" + "node": ">=6.0.0" } }, - "node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "node_modules/postcss-calc": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.1.tgz", + "integrity": "sha1-Ntd7qwI7Dsu5eJ2E3LI8SUEUVDY=", "dev": true, "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" + "css-unit-converter": "^1.1.1", + "postcss": "^7.0.5", + "postcss-selector-parser": "^5.0.0-rc.4", + "postcss-value-parser": "^3.3.1" } }, - "node_modules/p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha1-MQko/u+cnsxltosXaTAYpmXOoXU=", + "node_modules/postcss-colormin": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz", + "integrity": "sha1-rgYLzpPteUrHEmTwgTLVUJVr04E=", "dev": true, + "dependencies": { + "browserslist": "^4.0.0", + "color": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, "engines": { - "node": ">=6" + "node": ">=6.9.0" } }, - "node_modules/p-retry": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", - "integrity": "sha1-MWtMiJPiyNwc+okfQGxLQivr8yg=", + "node_modules/postcss-convert-values": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz", + "integrity": "sha1-yjgT7U2g+BL51DcDWE5Enr4Ymn8=", "dev": true, "dependencies": { - "retry": "^0.12.0" + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" }, "engines": { - "node": ">=6" + "node": ">=6.9.0" } }, - "node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "node_modules/postcss-discard-comments": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz", + "integrity": "sha1-H7q9LCRr/2qq15l7KwkY9NevQDM=", "dev": true, + "dependencies": { + "postcss": "^7.0.0" + }, "engines": { - "node": ">=4" + "node": ">=6.9.0" } }, - "node_modules/package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha1-b+7ayjXnVyWHbQsOZJdGl/7RRbA=", + "node_modules/postcss-discard-duplicates": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz", + "integrity": "sha1-P+EzzTyCKC5VD8myORdqkge3hOs=", "dev": true, "dependencies": { - "got": "^9.6.0", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^6.2.0" + "postcss": "^7.0.0" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" } }, - "node_modules/package-json/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=", + "node_modules/postcss-discard-empty": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz", + "integrity": "sha1-yMlR6fc+2UKAGUWERKAq2Qu592U=", "dev": true, - "bin": { - "semver": "bin/semver.js" + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/pako": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", - "integrity": "sha1-Qyi621CGpCaqkPVBl31JVdpclzI=", - "dev": true - }, - "node_modules/parallel-transform": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", - "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "node_modules/postcss-discard-overridden": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz", + "integrity": "sha1-ZSrvipZybwKfXj4AFG7npOdV/1c=", "dev": true, "dependencies": { - "cyclist": "~0.2.2", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/param-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "node_modules/postcss-load-config": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.0.tgz", + "integrity": "sha1-yE1pK3u3tB3c7ZTuYuirMbQXsAM=", "dev": true, "dependencies": { - "no-case": "^2.2.0" + "cosmiconfig": "^5.0.0", + "import-cwd": "^2.0.0" + }, + "engines": { + "node": ">= 4" } }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha1-aR0nCeeMefrjoVZiJFLQB2LKqqI=", + "node_modules/postcss-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", + "integrity": "sha1-a5eUPkfHLYRfqeA/Jzdz1OjdbC0=", "dev": true, "dependencies": { - "callsites": "^3.0.0" + "loader-utils": "^1.1.0", + "postcss": "^7.0.0", + "postcss-load-config": "^2.0.0", + "schema-utils": "^1.0.0" }, "engines": { - "node": ">=6" + "node": ">= 6" } }, - "node_modules/parent-module/node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha1-s2MKvYlDQy9Us/BRkjjjPNffL3M=", + "node_modules/postcss-loader/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, "engines": { - "node": ">=6" + "node": ">= 4" } }, - "node_modules/parse-asn1": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz", - "integrity": "sha1-N/Zij4I/vesic7TVQENKIvPvH8w=", + "node_modules/postcss-merge-longhand": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", + "integrity": "sha1-YvSaE+Sg7gTnuY9CuxYGLKJUniQ=", "dev": true, "dependencies": { - "asn1.js": "^4.0.0", - "browserify-aes": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" + "css-color-names": "0.0.4", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "stylehacks": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/parse-color": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-color/-/parse-color-1.0.0.tgz", - "integrity": "sha1-e3SLlag/A/FqlPU15S1/PZRlhhk=", + "node_modules/postcss-merge-rules": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", + "integrity": "sha1-NivqT/Wh+Y5AdacTxsslrv75plA=", "dev": true, "dependencies": { - "color-convert": "~0.5.0" + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "cssnano-util-same-parent": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0", + "vendors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/parse-color/node_modules/color-convert": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", - "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=", - "dev": true - }, - "node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "node_modules/postcss-merge-rules/node_modules/postcss-selector-parser": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", + "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", "dev": true, "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "dot-prop": "^4.1.1", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" }, "engines": { "node": ">=4" } }, - "node_modules/parse5": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", - "integrity": "sha1-bXhlbj2o14tOwLkG98CO8d/j9gg=", - "dev": true - }, - "node_modules/parseqs": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", - "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "node_modules/postcss-minify-font-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz", + "integrity": "sha1-zUw0TM5HQ0P6xdgiBqssvLiv1aY=", + "dev": true, "dependencies": { - "better-assert": "~1.0.0" + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/parseuri": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", - "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "node_modules/postcss-minify-gradients": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz", + "integrity": "sha1-k7KcL/UJnFNe7NpWxKpuZlpmNHE=", + "dev": true, "dependencies": { - "better-assert": "~1.0.0" + "cssnano-util-get-arguments": "^4.0.0", + "is-color-stop": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha1-naGee+6NEt/wUT7Vt2lXeTvC6NQ=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "node_modules/postcss-minify-params": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz", + "integrity": "sha1-a5zvAwwR41Jh+V9hjJADbWgNuHQ=", "dev": true, + "dependencies": { + "alphanum-sort": "^1.0.0", + "browserslist": "^4.0.0", + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "uniqs": "^2.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" } }, - "node_modules/path-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", - "integrity": "sha1-5sTd1+06onxoogzE5Q4aTug7vEo=", - "dev": true - }, - "node_modules/path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "node_modules/postcss-minify-selectors": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz", + "integrity": "sha1-4uXrQL/uUA0M2SQ1APX46kJi+9g=", "dev": true, + "dependencies": { + "alphanum-sort": "^1.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, "engines": { - "node": ">=4" + "node": ">=6.9.0" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "node_modules/postcss-minify-selectors/node_modules/postcss-selector-parser": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", + "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", "dev": true, + "dependencies": { + "dot-prop": "^4.1.1", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "node_modules/postcss-modules-extract-imports": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.1.tgz", + "integrity": "sha1-3IfjQUjsfqtfeR981YSYMzdbdBo=", "dev": true, - "engines": { - "node": ">=4" + "dependencies": { + "postcss": "^6.0.1" } }, - "node_modules/path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha1-1i27VnlAXXLEc37FhgDp3c8G0kw=", - "dev": true - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true - }, - "node_modules/path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha1-zvMdyOCho7sNEFwM2Xzzv0f0428=", + "node_modules/postcss-modules-extract-imports/node_modules/postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha1-YcgswyisYOZ3ZF+XkFTrmLwOMyQ=", "dev": true, "dependencies": { - "pify": "^3.0.0" + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" }, "engines": { - "node": ">=4" + "node": ">=4.0.0" } }, - "node_modules/path-type/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "node_modules/postcss-modules-extract-imports/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/pbkdf2": { - "version": "3.0.17", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", - "integrity": "sha1-l2wgZTBhexTrsyEUI597CTNuk6Y=", + "node_modules/postcss-modules-local-by-default": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", + "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", "dev": true, "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - }, - "engines": { - "node": ">=0.12" + "css-selector-tokenizer": "^0.7.0", + "postcss": "^6.0.1" } }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha1-SyzSXFDVmHNcUCkiJP2MbfQeMjE=", + "node_modules/postcss-modules-local-by-default/node_modules/postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha1-YcgswyisYOZ3ZF+XkFTrmLwOMyQ=", "dev": true, + "dependencies": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + }, "engines": { - "node": ">=6" + "node": ">=4.0.0" } }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "node_modules/postcss-modules-local-by-default/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "node_modules/postcss-modules-scope": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", + "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", "dev": true, "dependencies": { - "pinkie": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" + "css-selector-tokenizer": "^0.7.0", + "postcss": "^6.0.1" } }, - "node_modules/pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha1-J0kCDyOe2ZCIGx9xIQ1R62UjvqM=", + "node_modules/postcss-modules-scope/node_modules/postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha1-YcgswyisYOZ3ZF+XkFTrmLwOMyQ=", "dev": true, "dependencies": { - "find-up": "^3.0.0" + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" }, "engines": { - "node": ">=6" + "node": ">=4.0.0" } }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=", + "node_modules/postcss-modules-scope/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4=", + "node_modules/postcss-modules-values": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", + "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", "dev": true, "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" + "icss-replace-symbols": "^1.1.0", + "postcss": "^6.0.1" } }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", - "integrity": "sha1-QXyZQeYCepq8ulCS3SkE4lW1+8I=", + "node_modules/postcss-modules-values/node_modules/postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha1-YcgswyisYOZ3ZF+XkFTrmLwOMyQ=", "dev": true, "dependencies": { - "p-try": "^2.0.0" + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" }, "engines": { - "node": ">=6" + "node": ">=4.0.0" } }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=", + "node_modules/postcss-modules-values/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/pkg-dir/node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha1-yyhoVA4xPWHeWPr741zpAE1VQOY=", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", - "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=", + "node_modules/postcss-normalize-charset": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", + "integrity": "sha1-izWt067oOhNrBHHg1ZvlilAoXdQ=", "dev": true, "dependencies": { - "find-up": "^2.1.0" + "postcss": "^7.0.0" }, "engines": { - "node": ">=4" + "node": ">=6.9.0" } }, - "node_modules/plist": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.1.tgz", - "integrity": "sha1-qbkx0XwwTokS7wujvdYYK68uH4w=", + "node_modules/postcss-normalize-display-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", + "integrity": "sha1-Db4EpM6QY9RmftK+R2u4MMglk1o=", "dev": true, "dependencies": { - "base64-js": "^1.2.3", - "xmlbuilder": "^9.0.7", - "xmldom": "0.1.x" + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" }, "engines": { - "node": ">=6" - } - }, - "node_modules/pluralize": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha1-KYuJ34uTsCIdv0Ia0rGx6iP8Z3c=", - "dev": true, - "optional": true, - "engines": { - "node": ">=4" + "node": ">=6.9.0" } }, - "node_modules/pngparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pngparse/-/pngparse-2.0.1.tgz", - "integrity": "sha1-hoUt5N40n077HoUudSVlXlrF37g=" - }, - "node_modules/portfinder": { - "version": "1.0.21", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.21.tgz", - "integrity": "sha1-YOE5e5WsFwdJ23ADTs4wa5on4yQ=", + "node_modules/postcss-normalize-positions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", + "integrity": "sha1-BfdX+E8mBDc3g2ipH4ky1LECkX8=", "dev": true, "dependencies": { - "async": "^1.5.2", - "debug": "^2.2.0", - "mkdirp": "0.5.x" + "cssnano-util-get-arguments": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" }, "engines": { - "node": ">= 0.12.0" + "node": ">=6.9.0" } }, - "node_modules/portfinder/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "node_modules/postcss-normalize-repeat-style": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", + "integrity": "sha1-xOu8KJ85kaAo1EdRy90RkYsXkQw=", "dev": true, "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/portfinder/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true, + "cssnano-util-get-arguments": "^4.0.0", + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" } }, - "node_modules/postcss": { - "version": "7.0.17", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz", - "integrity": "sha1-TaG9/1Mi1KCsqrTYfz54JDa60x8=", + "node_modules/postcss-normalize-string": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", + "integrity": "sha1-zUTECrB6DHo23F6Zqs4eyk7CaQw=", "dev": true, "dependencies": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" }, "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/postcss-calc": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.1.tgz", - "integrity": "sha1-Ntd7qwI7Dsu5eJ2E3LI8SUEUVDY=", - "dev": true, - "dependencies": { - "css-unit-converter": "^1.1.1", - "postcss": "^7.0.5", - "postcss-selector-parser": "^5.0.0-rc.4", - "postcss-value-parser": "^3.3.1" + "node": ">=6.9.0" } }, - "node_modules/postcss-colormin": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz", - "integrity": "sha1-rgYLzpPteUrHEmTwgTLVUJVr04E=", + "node_modules/postcss-normalize-timing-functions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", + "integrity": "sha1-jgCcoqOUnNr4rSPmtquZy159KNk=", "dev": true, "dependencies": { - "browserslist": "^4.0.0", - "color": "^3.0.0", - "has": "^1.0.0", + "cssnano-util-get-match": "^4.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" }, @@ -11694,12 +11463,13 @@ "node": ">=6.9.0" } }, - "node_modules/postcss-convert-values": { + "node_modules/postcss-normalize-unicode": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz", - "integrity": "sha1-yjgT7U2g+BL51DcDWE5Enr4Ymn8=", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", + "integrity": "sha1-hBvUj9zzAZrUuqdJOj02O1KuHPs=", "dev": true, "dependencies": { + "browserslist": "^4.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" }, @@ -11707,2427 +11477,2291 @@ "node": ">=6.9.0" } }, - "node_modules/postcss-discard-comments": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz", - "integrity": "sha1-H7q9LCRr/2qq15l7KwkY9NevQDM=", + "node_modules/postcss-normalize-url": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz", + "integrity": "sha1-EOQ3+GvHx+WPe5ZS7YeNqqlfquE=", "dev": true, "dependencies": { - "postcss": "^7.0.0" + "is-absolute-url": "^2.0.0", + "normalize-url": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/postcss-discard-duplicates": { + "node_modules/postcss-normalize-whitespace": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz", - "integrity": "sha1-P+EzzTyCKC5VD8myORdqkge3hOs=", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz", + "integrity": "sha1-vx1AcP5Pzqh9E0joJdjMDF+qfYI=", "dev": true, "dependencies": { - "postcss": "^7.0.0" + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/postcss-discard-empty": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz", - "integrity": "sha1-yMlR6fc+2UKAGUWERKAq2Qu592U=", + "node_modules/postcss-ordered-values": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz", + "integrity": "sha1-DPdcgg7H1cTSgBiVWeC1ceusDu4=", "dev": true, "dependencies": { - "postcss": "^7.0.0" + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/postcss-discard-overridden": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz", - "integrity": "sha1-ZSrvipZybwKfXj4AFG7npOdV/1c=", + "node_modules/postcss-reduce-initial": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", + "integrity": "sha1-f9QuvqXpyBRgljniwuhK4nC6SN8=", "dev": true, "dependencies": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "has": "^1.0.0", "postcss": "^7.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/postcss-load-config": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.0.tgz", - "integrity": "sha1-yE1pK3u3tB3c7ZTuYuirMbQXsAM=", + "node_modules/postcss-reduce-transforms": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz", + "integrity": "sha1-F++kBerMbge+NBSlyi0QdGgdTik=", "dev": true, "dependencies": { - "cosmiconfig": "^5.0.0", - "import-cwd": "^2.0.0" + "cssnano-util-get-match": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" }, "engines": { - "node": ">= 4" + "node": ">=6.9.0" } }, - "node_modules/postcss-loader": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", - "integrity": "sha1-a5eUPkfHLYRfqeA/Jzdz1OjdbC0=", + "node_modules/postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha1-JJBENWaXsztk8aj3yAki3d7nGVw=", "dev": true, "dependencies": { - "loader-utils": "^1.1.0", - "postcss": "^7.0.0", - "postcss-load-config": "^2.0.0", - "schema-utils": "^1.0.0" + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" }, "engines": { - "node": ">= 6" + "node": ">=4" } }, - "node_modules/postcss-loader/node_modules/schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", + "node_modules/postcss-svgo": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz", + "integrity": "sha1-F7mXvHEbMzurFDqu07jT1uPTglg=", "dev": true, "dependencies": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" + "is-svg": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "svgo": "^1.0.0" }, "engines": { - "node": ">= 4" + "node": ">=6.9.0" } }, - "node_modules/postcss-merge-longhand": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", - "integrity": "sha1-YvSaE+Sg7gTnuY9CuxYGLKJUniQ=", + "node_modules/postcss-unique-selectors": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", + "integrity": "sha1-lEaRHzKJv9ZMbWgPBzwDsfnuS6w=", "dev": true, "dependencies": { - "css-color-names": "0.0.4", + "alphanum-sort": "^1.0.0", "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0", - "stylehacks": "^4.0.0" + "uniqs": "^2.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/postcss-merge-rules": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", - "integrity": "sha1-NivqT/Wh+Y5AdacTxsslrv75plA=", - "dev": true, - "dependencies": { - "browserslist": "^4.0.0", - "caniuse-api": "^3.0.0", - "cssnano-util-same-parent": "^4.0.0", - "postcss": "^7.0.0", - "postcss-selector-parser": "^3.0.0", - "vendors": "^1.0.0" - }, + "node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=", + "dev": true + }, + "node_modules/postcss/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true, "engines": { - "node": ">=6.9.0" + "node": ">=0.10.0" } }, - "node_modules/postcss-merge-rules/node_modules/postcss-selector-parser": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", - "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", + "node_modules/postcss/node_modules/supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha1-B2Srxpxj1ayELdSGfo0CXogN+PM=", "dev": true, "dependencies": { - "dot-prop": "^4.1.1", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" + "has-flag": "^3.0.0" }, "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/postcss-minify-font-values": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz", - "integrity": "sha1-zUw0TM5HQ0P6xdgiBqssvLiv1aY=", + "node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true, - "dependencies": { - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.8.0" } }, - "node_modules/postcss-minify-gradients": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz", - "integrity": "sha1-k7KcL/UJnFNe7NpWxKpuZlpmNHE=", + "node_modules/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", "dev": true, - "dependencies": { - "cssnano-util-get-arguments": "^4.0.0", - "is-color-stop": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, "engines": { - "node": ">=6.9.0" + "node": ">=4" } }, - "node_modules/postcss-minify-params": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz", - "integrity": "sha1-a5zvAwwR41Jh+V9hjJADbWgNuHQ=", + "node_modules/prettier": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.3.tgz", + "integrity": "sha1-jGIWhFO63vcC80tFtu6JlXSmpl0=", "dev": true, - "dependencies": { - "alphanum-sort": "^1.0.0", - "browserslist": "^4.0.0", - "cssnano-util-get-arguments": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0", - "uniqs": "^2.0.0" + "bin": { + "prettier": "bin-prettier.js" }, "engines": { - "node": ">=6.9.0" + "node": ">=4" } }, - "node_modules/postcss-minify-selectors": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz", - "integrity": "sha1-4uXrQL/uUA0M2SQ1APX46kJi+9g=", + "node_modules/pretty-bytes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", + "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", "dev": true, "dependencies": { - "alphanum-sort": "^1.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-selector-parser": "^3.0.0" + "get-stdin": "^4.0.1", + "meow": "^3.1.0" + }, + "bin": { + "pretty-bytes": "cli.js" }, "engines": { - "node": ">=6.9.0" + "node": ">=0.10.0" } }, - "node_modules/postcss-minify-selectors/node_modules/postcss-selector-parser": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", - "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", + "node_modules/pretty-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", + "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", "dev": true, "dependencies": { - "dot-prop": "^4.1.1", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - }, - "engines": { - "node": ">=4" + "renderkid": "^2.0.1", + "utila": "~0.4" } }, - "node_modules/postcss-modules-extract-imports": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.1.tgz", - "integrity": "sha1-3IfjQUjsfqtfeR981YSYMzdbdBo=", + "node_modules/private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha1-I4Hts2ifelPWUxkAYPz4ItLzaP8=", "dev": true, - "dependencies": { - "postcss": "^6.0.1" + "engines": { + "node": ">= 0.6" } }, - "node_modules/postcss-modules-extract-imports/node_modules/postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha1-YcgswyisYOZ3ZF+XkFTrmLwOMyQ=", + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", "dev": true, - "dependencies": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - }, "engines": { - "node": ">=4.0.0" + "node": ">= 0.6.0" } }, - "node_modules/postcss-modules-extract-imports/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha1-eCDZsWEgzFXKmud5JoCufbptf+I=", + "dev": true + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha1-foz42PW48jnBvGi+tOt4Vn1XLvg=", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=0.4.0" } }, - "node_modules/postcss-modules-local-by-default": { + "node_modules/progress-stream": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", - "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", + "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz", + "integrity": "sha1-LNPP6jO6OonJwSHsM0er6asSX3c=", "dev": true, "dependencies": { - "css-selector-tokenizer": "^0.7.0", - "postcss": "^6.0.1" + "speedometer": "~0.1.2", + "through2": "~0.2.3" } }, - "node_modules/postcss-modules-local-by-default/node_modules/postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha1-YcgswyisYOZ3ZF+XkFTrmLwOMyQ=", + "node_modules/progress-stream/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/progress-stream/node_modules/object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "dev": true + }, + "node_modules/progress-stream/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "dependencies": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - }, - "engines": { - "node": ">=4.0.0" + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" } }, - "node_modules/postcss-modules-local-by-default/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "node_modules/progress-stream/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "node_modules/progress-stream/node_modules/through2": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", + "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "readable-stream": "~1.1.9", + "xtend": "~2.1.1" } }, - "node_modules/postcss-modules-scope": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", - "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", + "node_modules/progress-stream/node_modules/xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", "dev": true, "dependencies": { - "css-selector-tokenizer": "^0.7.0", - "postcss": "^6.0.1" + "object-keys": "~0.4.0" + }, + "engines": { + "node": ">=0.4" } }, - "node_modules/postcss-modules-scope/node_modules/postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha1-YcgswyisYOZ3ZF+XkFTrmLwOMyQ=", + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "node_modules/proxy-addr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", + "integrity": "sha1-NMvWSi2B9LH9IedvnwbIpFKZ7jQ=", "dev": true, "dependencies": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.0" }, "engines": { - "node": ">=4.0.0" + "node": ">= 0.10" } }, - "node_modules/postcss-modules-scope/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "node_modules/psl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.2.0.tgz", + "integrity": "sha1-3xK1sbOjD1HDKerL3vmPOm4TbcY=", + "dev": true + }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha1-T8ydd6B+SLp1J+fL4N4z0HATMeA=", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" } }, - "node_modules/postcss-modules-values": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", - "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha1-tKIRaBW94vTh6mAjVOjHVWUQemQ=", "dev": true, "dependencies": { - "icss-replace-symbols": "^1.1.0", - "postcss": "^6.0.1" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, - "node_modules/postcss-modules-values/node_modules/postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha1-YcgswyisYOZ3ZF+XkFTrmLwOMyQ=", + "node_modules/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha1-NlE74karJ1cLGjdKXOJ4v9dDcM4=", "dev": true, "dependencies": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - }, - "engines": { - "node": ">=4.0.0" + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" } }, - "node_modules/postcss-modules-values/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "node_modules/pumpify/node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha1-Ejma3W5M91Jtlzy8i1zi4pCLOQk=", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, - "node_modules/postcss-normalize-charset": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", - "integrity": "sha1-izWt067oOhNrBHHg1ZvlilAoXdQ=", + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha1-tYsBCsQMIsVldhbI0sLALHv0eew=", "dev": true, - "dependencies": { - "postcss": "^7.0.0" - }, "engines": { - "node": ">=6.9.0" + "node": ">=6" } }, - "node_modules/postcss-normalize-display-values": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", - "integrity": "sha1-Db4EpM6QY9RmftK+R2u4MMglk1o=", + "node_modules/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", "dev": true, - "dependencies": { - "cssnano-util-get-match": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, "engines": { - "node": ">=6.9.0" + "node": ">=0.6.0", + "teleport": ">=0.2.0" } }, - "node_modules/postcss-normalize-positions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", - "integrity": "sha1-BfdX+E8mBDc3g2ipH4ky1LECkX8=", + "node_modules/qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha1-yzroBuh0BERYTvFUzo7pjUA/PjY=", "dev": true, - "dependencies": { - "cssnano-util-get-arguments": "^4.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, "engines": { - "node": ">=6.9.0" + "node": ">=0.6" } }, - "node_modules/postcss-normalize-repeat-style": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", - "integrity": "sha1-xOu8KJ85kaAo1EdRy90RkYsXkQw=", + "node_modules/query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha1-p4wBK3HBfgXy4/ojGd0zBoLvs8s=", "dev": true, "dependencies": { - "cssnano-util-get-arguments": "^4.0.0", - "cssnano-util-get-match": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=0.10.0" } }, - "node_modules/postcss-normalize-string": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", - "integrity": "sha1-zUTECrB6DHo23F6Zqs4eyk7CaQw=", + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", "dev": true, - "dependencies": { - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, "engines": { - "node": ">=6.9.0" + "node": ">=0.4.x" } }, - "node_modules/postcss-normalize-timing-functions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", - "integrity": "sha1-jgCcoqOUnNr4rSPmtquZy159KNk=", + "node_modules/querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", "dev": true, - "dependencies": { - "cssnano-util-get-match": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, "engines": { - "node": ">=6.9.0" + "node": ">=0.4.x" } }, - "node_modules/postcss-normalize-unicode": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", - "integrity": "sha1-hBvUj9zzAZrUuqdJOj02O1KuHPs=", + "node_modules/querystringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz", + "integrity": "sha1-YOWl/WSn+L+k0qsu1v30yFutFU4=", + "dev": true + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha1-32+ENy8CcNxlzfYpE0mrekc9Tyo=", "dev": true, "dependencies": { - "browserslist": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "engines": { - "node": ">=6.9.0" + "safe-buffer": "^5.1.0" } }, - "node_modules/postcss-normalize-url": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz", - "integrity": "sha1-EOQ3+GvHx+WPe5ZS7YeNqqlfquE=", + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha1-ySGW/IarQr6YPxvzF3giSTHWFFg=", "dev": true, "dependencies": { - "is-absolute-url": "^2.0.0", - "normalize-url": "^3.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "engines": { - "node": ">=6.9.0" + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" } }, - "node_modules/postcss-normalize-whitespace": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz", - "integrity": "sha1-vx1AcP5Pzqh9E0joJdjMDF+qfYI=", + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha1-PPNwI9GZ4cJNGlW4SADC8+ZGgDE=", "dev": true, - "dependencies": { - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.6" } }, - "node_modules/postcss-ordered-values": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz", - "integrity": "sha1-DPdcgg7H1cTSgBiVWeC1ceusDu4=", + "node_modules/raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha1-oc5vucm8NWylLoklarWQWeE9AzI=", "dev": true, "dependencies": { - "cssnano-util-get-arguments": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.8" } }, - "node_modules/postcss-reduce-initial": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", - "integrity": "sha1-f9QuvqXpyBRgljniwuhK4nC6SN8=", + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha1-zZJL9SAKB1uDwYjNa54hG3/A0+0=", "dev": true, "dependencies": { - "browserslist": "^4.0.0", - "caniuse-api": "^3.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0" + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, - "engines": { - "node": ">=6.9.0" + "bin": { + "rc": "cli.js" } }, - "node_modules/postcss-reduce-transforms": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz", - "integrity": "sha1-F++kBerMbge+NBSlyi0QdGgdTik=", + "node_modules/read-config-file": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-3.2.2.tgz", + "integrity": "sha1-V7v/fdl8ryN9DWJb1UHG0O+00Gc=", "dev": true, "dependencies": { - "cssnano-util-get-match": "^4.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "engines": { - "node": ">=6.9.0" + "ajv": "^6.9.2", + "ajv-keywords": "^3.4.0", + "bluebird-lst": "^1.0.7", + "dotenv": "^6.2.0", + "dotenv-expand": "^4.2.0", + "fs-extra-p": "^7.0.1", + "js-yaml": "^3.12.1", + "json5": "^2.1.0", + "lazy-val": "^1.0.4" } }, - "node_modules/postcss-selector-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", - "integrity": "sha1-JJBENWaXsztk8aj3yAki3d7nGVw=", + "node_modules/read-config-file/node_modules/dotenv": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz", + "integrity": "sha1-lBwEEFNdlCyL7PKNPzV9vZ1HYGQ=", "dev": true, - "dependencies": { - "cssesc": "^2.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - }, "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/postcss-svgo": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz", - "integrity": "sha1-F7mXvHEbMzurFDqu07jT1uPTglg=", + "node_modules/read-config-file/node_modules/dotenv-expand": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-4.2.0.tgz", + "integrity": "sha1-3vHxyl1gWdJKdm5YeULCEQbOEnU=", + "dev": true + }, + "node_modules/read-config-file/node_modules/fs-extra-p": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra-p/-/fs-extra-p-7.0.1.tgz", + "integrity": "sha1-TuwLbfoVD6kPbd13O0+x1VytVOM=", "dev": true, "dependencies": { - "is-svg": "^3.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0", - "svgo": "^1.0.0" + "bluebird-lst": "^1.0.7", + "fs-extra": "^7.0.1" }, "engines": { - "node": ">=6.9.0" + "node": ">=6 <7 || >=8" } }, - "node_modules/postcss-unique-selectors": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", - "integrity": "sha1-lEaRHzKJv9ZMbWgPBzwDsfnuS6w=", + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha1-e/KVQ4yloz5WzTDgU7NO5yUMk8w=", "dev": true, "dependencies": { - "alphanum-sort": "^1.0.0", - "postcss": "^7.0.0", - "uniqs": "^2.0.0" + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=8" } }, - "node_modules/postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=", - "dev": true - }, - "node_modules/postcss/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "node_modules/read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true, + "dependencies": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/postcss/node_modules/supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha1-B2Srxpxj1ayELdSGfo0CXogN+PM=", + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "node_modules/read-pkg-up/node_modules/path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, + "dependencies": { + "pinkie-promise": "^2.0.0" + }, "engines": { - "node": ">= 0.8.0" + "node": ">=0.10.0" } }, - "node_modules/prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "node_modules/read-pkg-up/node_modules/path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/prettier": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.3.tgz", - "integrity": "sha1-jGIWhFO63vcC80tFtu6JlXSmpl0=", + "node_modules/read-pkg-up/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/pretty-bytes": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", - "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", + "node_modules/read-pkg-up/node_modules/read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, "dependencies": { - "get-stdin": "^4.0.1", - "meow": "^3.1.0" - }, - "bin": { - "pretty-bytes": "cli.js" + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/pretty-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", - "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", + "node_modules/read-pkg/node_modules/parse-json": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", + "integrity": "sha1-c+URTJhtFD76NxLU6iTbmkJm9g8=", "dev": true, "dependencies": { - "renderkid": "^2.0.1", - "utila": "~0.4" + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" } }, - "node_modules/private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha1-I4Hts2ifelPWUxkAYPz4ItLzaP8=", + "node_modules/readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=", "dev": true, - "engines": { - "node": ">= 0.6" + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha1-DodiKjMlqjPokihcr4tOhGUppSU=", "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, "engines": { - "node": ">= 0.6.0" + "node": ">=0.10" } }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha1-eCDZsWEgzFXKmud5JoCufbptf+I=", - "dev": true - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha1-foz42PW48jnBvGi+tOt4Vn1XLvg=", + "node_modules/redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", "dev": true, + "dependencies": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + }, "engines": { - "node": ">=0.4.0" + "node": ">=0.10.0" } }, - "node_modules/progress-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz", - "integrity": "sha1-LNPP6jO6OonJwSHsM0er6asSX3c=", + "node_modules/redent/node_modules/strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", "dev": true, "dependencies": { - "speedometer": "~0.1.2", - "through2": "~0.2.3" + "get-stdin": "^4.0.1" + }, + "bin": { + "strip-indent": "cli.js" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/progress-stream/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "node_modules/progress-stream/node_modules/object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "node_modules/regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha1-SoVuxLVuQHfFV1icroXnpMiGmhE=", "dev": true }, - "node_modules/progress-stream/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "node_modules/regenerate-unicode-properties": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", + "integrity": "sha1-71Hg8OpK1CS3e/fLQfPgFccKPw4=", "dev": true, "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "regenerate": "^1.4.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/progress-stream/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "node_modules/regenerator-runtime": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", + "integrity": "sha1-fPanfY9cb2Drc8X8GVWyzrAea/U=", "dev": true }, - "node_modules/progress-stream/node_modules/through2": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", - "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", + "node_modules/regenerator-transform": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", + "integrity": "sha1-Oy/OThq3cywI9mXf2zFHScfd0vs=", "dev": true, "dependencies": { - "readable-stream": "~1.1.9", - "xtend": "~2.1.1" + "private": "^0.1.6" } }, - "node_modules/progress-stream/node_modules/xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "node_modules/regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=", "dev": true, "dependencies": { - "object-keys": "~0.4.0" + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" }, "engines": { - "node": ">=0.4" + "node": ">=0.10.0" } }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true + "node_modules/regexp-tree": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.11.tgz", + "integrity": "sha1-ycfwD89yLgpWxzkJg6emPdbCcvM=", + "dev": true, + "bin": { + "regexp-tree": "bin/regexp-tree" + } }, - "node_modules/proxy-addr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", - "integrity": "sha1-NMvWSi2B9LH9IedvnwbIpFKZ7jQ=", + "node_modules/regexpp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", + "integrity": "sha1-DjUW3Qt5BPQT0tQZPc5GGMOmias=", "dev": true, - "dependencies": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.0" - }, + "optional": true, "engines": { - "node": ">= 0.10" + "node": ">=4.0.0" } }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "node_modules/psl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.2.0.tgz", - "integrity": "sha1-3xK1sbOjD1HDKerL3vmPOm4TbcY=", - "dev": true - }, - "node_modules/public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha1-T8ydd6B+SLp1J+fL4N4z0HATMeA=", + "node_modules/regexpu-core": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", + "integrity": "sha1-CA2dAiiaqH/hZnpPUTa8mKauuq4=", "dev": true, "dependencies": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.0.2", + "regjsgen": "^0.5.0", + "regjsparser": "^0.6.0", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.1.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha1-tKIRaBW94vTh6mAjVOjHVWUQemQ=", + "node_modules/registry-auth-token": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.0.0.tgz", + "integrity": "sha1-MOVZYe7Hc3naVR6lxM9Dy/A1Ir4=", "dev": true, "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "rc": "^1.2.8", + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": ">=6.0.0" } }, - "node_modules/pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha1-NlE74karJ1cLGjdKXOJ4v9dDcM4=", + "node_modules/registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha1-6YM0tQ1UNLgRNrROxjjZwgCcUAk=", "dev": true, "dependencies": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" + "rc": "^1.2.8" + }, + "engines": { + "node": ">=8" } }, - "node_modules/pumpify/node_modules/pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha1-Ejma3W5M91Jtlzy8i1zi4pCLOQk=", + "node_modules/regjsgen": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", + "integrity": "sha1-p2NNwI+JIJwgSa3aNSVxH7lyZd0=", + "dev": true + }, + "node_modules/regjsparser": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", + "integrity": "sha1-8eaui32iuulsmTmbhozWyTOiupw=", "dev": true, "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" } }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha1-tYsBCsQMIsVldhbI0sLALHv0eew=", + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", "dev": true, - "engines": { - "node": ">=6" + "bin": { + "jsesc": "bin/jsesc" } }, - "node_modules/q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", "dev": true, "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" + "node": ">= 0.10" } }, - "node_modules/qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha1-yzroBuh0BERYTvFUzo7pjUA/PjY=", + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "node_modules/renderkid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.3.tgz", + "integrity": "sha1-OAF5wv9a4TZcUivy/Pz/AcW3QUk=", "dev": true, - "engines": { - "node": ">=0.6" + "dependencies": { + "css-select": "^1.1.0", + "dom-converter": "^0.2", + "htmlparser2": "^3.3.0", + "strip-ansi": "^3.0.0", + "utila": "^0.4.0" } }, - "node_modules/query-string": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", - "integrity": "sha1-p4wBK3HBfgXy4/ojGd0zBoLvs8s=", + "node_modules/renderkid/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true, - "dependencies": { - "decode-uri-component": "^0.2.0", - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" - }, "engines": { "node": ">=0.10.0" } }, - "node_modules/querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "node_modules/renderkid/node_modules/css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", "dev": true, - "engines": { - "node": ">=0.4.x" + "dependencies": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" } }, - "node_modules/querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "node_modules/renderkid/node_modules/domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", "dev": true, - "engines": { - "node": ">=0.4.x" + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" } }, - "node_modules/querystringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz", - "integrity": "sha1-YOWl/WSn+L+k0qsu1v30yFutFU4=", - "dev": true - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha1-32+ENy8CcNxlzfYpE0mrekc9Tyo=", + "node_modules/renderkid/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "dependencies": { - "safe-buffer": "^5.1.0" + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha1-ySGW/IarQr6YPxvzF3giSTHWFFg=", + "node_modules/repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha1-eC4NglwMWjuzlzH4Tv7mt0Lmsc4=", "dev": true, - "dependencies": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha1-PPNwI9GZ4cJNGlW4SADC8+ZGgDE=", + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true, "engines": { - "node": ">= 0.6" + "node": ">=0.10" } }, - "node_modules/raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha1-oc5vucm8NWylLoklarWQWeE9AzI=", + "node_modules/repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "dev": true, "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "is-finite": "^1.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">=0.10.0" } }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha1-zZJL9SAKB1uDwYjNa54hG3/A0+0=", + "node_modules/request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha1-nC/KT301tZLv5Xx/ClXoEFIST+8=", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", "dev": true, "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" }, - "bin": { - "rc": "cli.js" + "engines": { + "node": ">= 4" } }, - "node_modules/read-config-file": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-3.2.2.tgz", - "integrity": "sha1-V7v/fdl8ryN9DWJb1UHG0O+00Gc=", + "node_modules/request-promise-core": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", + "integrity": "sha1-M59qq6vK/bMceZ/xWHADNjAdM0Y=", "dev": true, "dependencies": { - "ajv": "^6.9.2", - "ajv-keywords": "^3.4.0", - "bluebird-lst": "^1.0.7", - "dotenv": "^6.2.0", - "dotenv-expand": "^4.2.0", - "fs-extra-p": "^7.0.1", - "js-yaml": "^3.12.1", - "json5": "^2.1.0", - "lazy-val": "^1.0.4" - } - }, - "node_modules/read-config-file/node_modules/dotenv": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz", - "integrity": "sha1-lBwEEFNdlCyL7PKNPzV9vZ1HYGQ=", - "dev": true, + "lodash": "^4.17.11" + }, "engines": { - "node": ">=6" + "node": ">=0.10.0" + }, + "peerDependencies": { + "request": "^2.34" } }, - "node_modules/read-config-file/node_modules/dotenv-expand": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-4.2.0.tgz", - "integrity": "sha1-3vHxyl1gWdJKdm5YeULCEQbOEnU=", - "dev": true - }, - "node_modules/read-config-file/node_modules/fs-extra-p": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra-p/-/fs-extra-p-7.0.1.tgz", - "integrity": "sha1-TuwLbfoVD6kPbd13O0+x1VytVOM=", + "node_modules/request-promise-native": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz", + "integrity": "sha1-pJhopiS96lBp8SUdCoNuDYmqLFk=", + "deprecated": "request-promise-native has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142", "dev": true, "dependencies": { - "bluebird-lst": "^1.0.7", - "fs-extra": "^7.0.1" + "request-promise-core": "1.1.2", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" }, "engines": { - "node": ">=6 <7 || >=8" + "node": ">=0.12.0" + }, + "peerDependencies": { + "request": "^2.34" } }, - "node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha1-e/KVQ4yloz5WzTDgU7NO5yUMk8w=", + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, - "dependencies": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, "engines": { "node": ">=0.10.0" } }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha1-0LMp7MfMD2Fkn2IhW+aa9UqomJs=", + "dev": true + }, + "node_modules/require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", "dev": true, + "optional": true, "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/read-pkg-up/node_modules/path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "node_modules/reselect": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-3.0.1.tgz", + "integrity": "sha1-79qpjqdFEyTQkrKyFjpqHXqaIUc=", + "dev": true + }, + "node_modules/resolve": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha1-6hDYEQN2mC/vV434/DC5rDCgej4=", "dev": true, "dependencies": { - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" + "path-parse": "^1.0.6" } }, - "node_modules/read-pkg-up/node_modules/path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "node_modules/resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", "dev": true, "dependencies": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "resolve-from": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/read-pkg-up/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/read-pkg-up/node_modules/read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "node_modules/resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", "dev": true, - "dependencies": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, + "optional": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/read-pkg/node_modules/parse-json": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", - "integrity": "sha1-c+URTJhtFD76NxLU6iTbmkJm9g8=", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - } + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "deprecated": "https://github.com/lydell/resolve-url#deprecated", + "dev": true }, - "node_modules/readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=", + "node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", "dev": true, "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "lowercase-keys": "^1.0.0" } }, - "node_modules/readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha1-DodiKjMlqjPokihcr4tOhGUppSU=", + "node_modules/restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "dev": true, "dependencies": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" }, "engines": { - "node": ">=0.10" + "node": ">=4" } }, - "node_modules/redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w=", "dev": true, - "dependencies": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - }, "engines": { - "node": ">=0.10.0" + "node": ">=0.12" } }, - "node_modules/redent/node_modules/strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", "dev": true, - "dependencies": { - "get-stdin": "^4.0.1" - }, - "bin": { - "strip-indent": "cli.js" - }, "engines": { - "node": ">=0.10.0" + "node": ">= 4" } }, - "node_modules/regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha1-SoVuxLVuQHfFV1icroXnpMiGmhE=", + "node_modules/rgb-regex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", + "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=", "dev": true }, - "node_modules/regenerate-unicode-properties": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", - "integrity": "sha1-71Hg8OpK1CS3e/fLQfPgFccKPw4=", + "node_modules/rgb2hex": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.1.9.tgz", + "integrity": "sha1-XT4OFLAXe1aObw1bQ+NPv9tnA0Y=", + "dev": true + }, + "node_modules/rgba-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", + "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=", + "dev": true + }, + "node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha1-stEE/g2Psnz54KHNqCYt04M8bKs=", "dev": true, "dependencies": { - "regenerate": "^1.4.0" + "glob": "^7.1.3" }, - "engines": { - "node": ">=4" + "bin": { + "rimraf": "bin.js" } }, - "node_modules/regenerator-runtime": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", - "integrity": "sha1-fPanfY9cb2Drc8X8GVWyzrAea/U=", - "dev": true - }, - "node_modules/regenerator-transform": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", - "integrity": "sha1-Oy/OThq3cywI9mXf2zFHScfd0vs=", + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha1-ocGm9iR1FXe6XQeRTLyShQWFiQw=", "dev": true, "dependencies": { - "private": "^0.1.6" + "hash-base": "^3.0.0", + "inherits": "^2.0.1" } }, - "node_modules/regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=", - "dev": true, + "node_modules/roslib": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/roslib/-/roslib-1.0.1.tgz", + "integrity": "sha512-kmnjHpzdGh5sNbh24qg079w99Bvf4ROboMB8KA48uwMFE2YxhkeoJsmdeIjq3jnrmRyogogpsQARBgOTjxGU2g==", "dependencies": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" + "cbor-js": "^0.1.0", + "eventemitter2": "^4.1.0", + "object-assign": "^4.0.1", + "pngparse": "^2.0.1", + "socket.io": "2.2.0", + "ws": "^3.3.1", + "xmldom": "^0.1.19" }, "engines": { - "node": ">=0.10.0" + "node": ">=0.10" } }, - "node_modules/regexp-tree": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.11.tgz", - "integrity": "sha1-ycfwD89yLgpWxzkJg6emPdbCcvM=", - "dev": true, - "bin": { - "regexp-tree": "bin/regexp-tree" + "node_modules/roslib/node_modules/ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dependencies": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" } }, - "node_modules/regexpp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", - "integrity": "sha1-DjUW3Qt5BPQT0tQZPc5GGMOmias=", + "node_modules/run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", "dev": true, - "optional": true, + "dependencies": { + "is-promise": "^2.1.0" + }, "engines": { - "node": ">=4.0.0" + "node": ">=0.12.0" } }, - "node_modules/regexpu-core": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", - "integrity": "sha1-CA2dAiiaqH/hZnpPUTa8mKauuq4=", + "node_modules/run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", "dev": true, "dependencies": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.0.2", - "regjsgen": "^0.5.0", - "regjsparser": "^0.6.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.1.0" - }, - "engines": { - "node": ">=4" + "aproba": "^1.1.1" } }, - "node_modules/registry-auth-token": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.0.0.tgz", - "integrity": "sha1-MOVZYe7Hc3naVR6lxM9Dy/A1Ir4=", + "node_modules/rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "dev": true + }, + "node_modules/rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", "dev": true, "dependencies": { - "rc": "^1.2.8", - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": ">=6.0.0" + "rx-lite": "*" } }, - "node_modules/registry-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", - "integrity": "sha1-6YM0tQ1UNLgRNrROxjjZwgCcUAk=", + "node_modules/rxjs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz", + "integrity": "sha1-LjXOgVzUbYTQKiCftOWSHgUdvsc=", "dev": true, "dependencies": { - "rc": "^1.2.8" + "tslib": "^1.9.0" }, "engines": { - "node": ">=8" + "npm": ">=2.0.0" } }, - "node_modules/regjsgen": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", - "integrity": "sha1-p2NNwI+JIJwgSa3aNSVxH7lyZd0=", - "dev": true + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=" }, - "node_modules/regjsparser": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha1-8eaui32iuulsmTmbhozWyTOiupw=", + "node_modules/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" + "ret": "~0.1.10" } }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=", + "dev": true + }, + "node_modules/sanitize-filename": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.1.tgz", + "integrity": "sha1-YS2hyWRz+gLczaktzVtKsWSmdyo=", "dev": true, - "bin": { - "jsesc": "bin/jsesc" + "dependencies": { + "truncate-utf8-bytes": "^1.0.0" } }, - "node_modules/relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk=", + "dev": true + }, + "node_modules/schema-utils": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", + "integrity": "sha1-unT1l9K+LqiAExdG7hfQoJPGgYc=", "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0" + }, "engines": { - "node": ">= 0.10" + "node": ">= 4" } }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", "dev": true }, - "node_modules/renderkid": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.3.tgz", - "integrity": "sha1-OAF5wv9a4TZcUivy/Pz/AcW3QUk=", + "node_modules/selfsigned": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.4.tgz", + "integrity": "sha1-zdfsz8pO12NdR6CL8tXTB0CS4s0=", "dev": true, "dependencies": { - "css-select": "^1.1.0", - "dom-converter": "^0.2", - "htmlparser2": "^3.3.0", - "strip-ansi": "^3.0.0", - "utila": "^0.4.0" + "node-forge": "0.7.5" } }, - "node_modules/renderkid/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "node_modules/semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha1-eQp89v6lRZuslhELKbYEEtyP+Ws=", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/semver-diff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", "dev": true, + "dependencies": { + "semver": "^5.0.3" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/renderkid/node_modules/css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "node_modules/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha1-wdiwWfeQD3Rm3Uk4vcROEd2zdsg=", "dev": true, "dependencies": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/renderkid/node_modules/domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "dependencies": { - "dom-serializer": "0", - "domelementtype": "1" + "ms": "2.0.0" } }, - "node_modules/renderkid/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE=", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo=", + "dev": true + }, + "node_modules/serialize-javascript": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz", + "integrity": "sha1-1uDfsqODKoyURo5usduX5VoZKmU=", + "dev": true + }, + "node_modules/serve": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/serve/-/serve-14.2.3.tgz", + "integrity": "sha512-VqUFMC7K3LDGeGnJM9h56D3XGKb6KGgOw0cVNtA26yYXHCcpxf3xwCTUaQoWlVS7i8Jdh3GjQkOB23qsXyjoyQ==", "dev": true, "dependencies": { - "ansi-regex": "^2.0.0" + "@zeit/schemas": "2.36.0", + "ajv": "8.12.0", + "arg": "5.0.2", + "boxen": "7.0.0", + "chalk": "5.0.1", + "chalk-template": "0.4.0", + "clipboardy": "3.0.0", + "compression": "1.7.4", + "is-port-reachable": "4.0.0", + "serve-handler": "6.1.5", + "update-check": "1.5.4" + }, + "bin": { + "serve": "build/main.js" }, "engines": { - "node": ">=0.10.0" + "node": ">= 14" } }, - "node_modules/repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha1-eC4NglwMWjuzlzH4Tv7mt0Lmsc4=", + "node_modules/serve-handler": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz", + "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==", + "dev": true, + "dependencies": { + "bytes": "3.0.0", + "content-disposition": "0.5.2", + "fast-url-parser": "1.1.3", + "mime-types": "2.1.18", + "minimatch": "3.1.2", + "path-is-inside": "1.0.2", + "path-to-regexp": "2.2.1", + "range-parser": "1.2.0" + } + }, + "node_modules/serve-handler/node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "node_modules/serve-handler/node_modules/content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==", "dev": true, "engines": { - "node": ">=0.10" + "node": ">= 0.6" } }, - "node_modules/repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "node_modules/serve-handler/node_modules/mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-handler/node_modules/mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", "dev": true, "dependencies": { - "is-finite": "^1.0.0" + "mime-db": "~1.33.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha1-nC/KT301tZLv5Xx/ClXoEFIST+8=", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "node_modules/serve-handler/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 4" + "node": "*" } }, - "node_modules/request-promise-core": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", - "integrity": "sha1-M59qq6vK/bMceZ/xWHADNjAdM0Y=", + "node_modules/serve-handler/node_modules/path-to-regexp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", + "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==", + "dev": true + }, + "node_modules/serve-handler/node_modules/range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==", "dev": true, - "dependencies": { - "lodash": "^4.17.11" - }, "engines": { - "node": ">=0.10.0" - }, - "peerDependencies": { - "request": "^2.34" + "node": ">= 0.6" } }, - "node_modules/request-promise-native": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz", - "integrity": "sha1-pJhopiS96lBp8SUdCoNuDYmqLFk=", - "deprecated": "request-promise-native has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142", + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", "dev": true, "dependencies": { - "request-promise-core": "1.1.2", - "stealthy-require": "^1.1.1", - "tough-cookie": "^2.3.3" - }, - "engines": { - "node": ">=0.12.0" + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" }, - "peerDependencies": { - "request": "^2.34" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8.0" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha1-0LMp7MfMD2Fkn2IhW+aa9UqomJs=", - "dev": true - }, - "node_modules/require-uncached": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, - "optional": true, "dependencies": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, - "node_modules/reselect": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-3.0.1.tgz", - "integrity": "sha1-79qpjqdFEyTQkrKyFjpqHXqaIUc=", + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, - "node_modules/resolve": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", - "integrity": "sha1-6hDYEQN2mC/vV434/DC5rDCgej4=", - "dev": true, - "dependencies": { - "path-parse": "^1.0.6" - } + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY=", + "dev": true }, - "node_modules/resolve-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", - "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "node_modules/serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha1-Zm5jbcTwEPfvKZcKiKZ0MgiYsvk=", "dev": true, "dependencies": { - "resolve-from": "^3.0.0" + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" }, "engines": { - "node": ">=4" + "node": ">= 0.8.0" } }, - "node_modules/resolve-cwd/node_modules/resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "node_modules/serve/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dev": true, - "engines": { - "node": ">=4" + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "node_modules/serve/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "optional": true, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "deprecated": "https://github.com/lydell/resolve-url#deprecated", - "dev": true - }, - "node_modules/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "node_modules/serve/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, - "dependencies": { - "lowercase-keys": "^1.0.0" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "node_modules/serve/node_modules/boxen": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.0.0.tgz", + "integrity": "sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg==", "dev": true, "dependencies": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" + "ansi-align": "^3.0.1", + "camelcase": "^7.0.0", + "chalk": "^5.0.1", + "cli-boxes": "^3.0.0", + "string-width": "^5.1.2", + "type-fest": "^2.13.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.0.1" }, "engines": { - "node": ">=4" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w=", + "node_modules/serve/node_modules/camelcase": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", + "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", "dev": true, "engines": { - "node": ">=0.12" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "node_modules/serve/node_modules/chalk": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.1.tgz", + "integrity": "sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==", "dev": true, "engines": { - "node": ">= 4" - } - }, - "node_modules/rgb-regex": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", - "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=", - "dev": true - }, - "node_modules/rgb2hex": { - "version": "0.1.9", - "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.1.9.tgz", - "integrity": "sha1-XT4OFLAXe1aObw1bQ+NPv9tnA0Y=", - "dev": true - }, - "node_modules/rgba-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", - "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=", - "dev": true - }, - "node_modules/rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha1-stEE/g2Psnz54KHNqCYt04M8bKs=", - "dev": true, - "dependencies": { - "glob": "^7.1.3" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, - "bin": { - "rimraf": "bin.js" + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha1-ocGm9iR1FXe6XQeRTLyShQWFiQw=", + "node_modules/serve/node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/roslib": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/roslib/-/roslib-1.0.1.tgz", - "integrity": "sha512-kmnjHpzdGh5sNbh24qg079w99Bvf4ROboMB8KA48uwMFE2YxhkeoJsmdeIjq3jnrmRyogogpsQARBgOTjxGU2g==", + "node_modules/serve/node_modules/clipboardy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-3.0.0.tgz", + "integrity": "sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==", + "dev": true, "dependencies": { - "cbor-js": "^0.1.0", - "eventemitter2": "^4.1.0", - "object-assign": "^4.0.1", - "pngparse": "^2.0.1", - "socket.io": "2.2.0", - "ws": "^3.3.1", - "xmldom": "^0.1.19" + "arch": "^2.2.0", + "execa": "^5.1.1", + "is-wsl": "^2.2.0" }, "engines": { - "node": ">=0.10" - } - }, - "node_modules/roslib/node_modules/ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dependencies": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "node_modules/serve/node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "dependencies": { - "is-promise": "^2.1.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": ">=0.12.0" + "node": ">= 8" } }, - "node_modules/run-queue": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", - "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "node_modules/serve/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/serve/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "dependencies": { - "aproba": "^1.1.1" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/rx-lite": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "node_modules/serve/node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "node_modules/rx-lite-aggregates": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", - "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "node_modules/serve/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, - "dependencies": { - "rx-lite": "*" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/rxjs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz", - "integrity": "sha1-LjXOgVzUbYTQKiCftOWSHgUdvsc=", + "node_modules/serve/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, "engines": { - "npm": ">=2.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=" - }, - "node_modules/safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "node_modules/serve/node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "dev": true, "dependencies": { - "ret": "~0.1.10" + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=", + "node_modules/serve/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, - "node_modules/sanitize-filename": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.1.tgz", - "integrity": "sha1-YS2hyWRz+gLczaktzVtKsWSmdyo=", + "node_modules/serve/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, - "dependencies": { - "truncate-utf8-bytes": "^1.0.0" + "engines": { + "node": ">=6" } }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk=", - "dev": true - }, - "node_modules/schema-utils": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", - "integrity": "sha1-unT1l9K+LqiAExdG7hfQoJPGgYc=", + "node_modules/serve/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, "dependencies": { - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0" + "path-key": "^3.0.0" }, "engines": { - "node": ">= 4" + "node": ">=8" } }, - "node_modules/select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", - "dev": true - }, - "node_modules/selfsigned": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.4.tgz", - "integrity": "sha1-zdfsz8pO12NdR6CL8tXTB0CS4s0=", + "node_modules/serve/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "dependencies": { - "node-forge": "0.7.5" + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha1-eQp89v6lRZuslhELKbYEEtyP+Ws=", + "node_modules/serve/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, - "bin": { - "semver": "bin/semver" + "engines": { + "node": ">=8" } }, - "node_modules/semver-diff": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", - "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "node_modules/serve/node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "dependencies": { - "semver": "^5.0.3" + "shebang-regex": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha1-wdiwWfeQD3Rm3Uk4vcROEd2zdsg=", + "node_modules/serve/node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "dependencies": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "node_modules/serve/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "dependencies": { - "ms": "2.0.0" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/send/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE=", + "node_modules/serve/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, - "bin": { - "mime": "cli.js" + "dependencies": { + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=4" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/send/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo=", - "dev": true - }, - "node_modules/serialize-javascript": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz", - "integrity": "sha1-1uDfsqODKoyURo5usduX5VoZKmU=", - "dev": true + "node_modules/serve/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/serve": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/serve/-/serve-14.2.3.tgz", - "integrity": "sha512-VqUFMC7K3LDGeGnJM9h56D3XGKb6KGgOw0cVNtA26yYXHCcpxf3xwCTUaQoWlVS7i8Jdh3GjQkOB23qsXyjoyQ==", + "node_modules/serve/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "dependencies": { - "@zeit/schemas": "2.36.0", - "ajv": "8.12.0", - "arg": "5.0.2", - "boxen": "7.0.0", - "chalk": "5.0.1", - "chalk-template": "0.4.0", - "clipboardy": "3.0.0", - "compression": "1.7.4", - "is-port-reachable": "4.0.0", - "serve-handler": "6.1.5", - "update-check": "1.5.4" + "isexe": "^2.0.0" }, "bin": { - "serve": "build/main.js" + "node-which": "bin/node-which" }, "engines": { - "node": ">= 14" + "node": ">= 8" } }, - "node_modules/serve-handler": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz", - "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==", + "node_modules/serve/node_modules/widest-line": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", "dev": true, "dependencies": { - "bytes": "3.0.0", - "content-disposition": "0.5.2", - "fast-url-parser": "1.1.3", - "mime-types": "2.1.18", - "minimatch": "3.1.2", - "path-is-inside": "1.0.2", - "path-to-regexp": "2.2.1", - "range-parser": "1.2.0" - } - }, - "node_modules/serve-handler/node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", - "dev": true, + "string-width": "^5.0.1" + }, "engines": { - "node": ">= 0.8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/serve-handler/node_modules/content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==", + "node_modules/serve/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, "engines": { - "node": ">= 0.6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/serve-handler/node_modules/mime-db": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", - "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "node_modules/set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", "dev": true, "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } }, - "node_modules/serve-handler/node_modules/mime-types": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", - "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "node_modules/set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha1-oY1AUw5vB95CKMfe/kInr4ytAFs=", "dev": true, "dependencies": { - "mime-db": "~1.33.0" + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" }, "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } }, - "node_modules/serve-handler/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/set-value/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "is-extendable": "^0.1.0" }, "engines": { - "node": "*" + "node": ">=0.10.0" } }, - "node_modules/serve-handler/node_modules/path-to-regexp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", - "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==", + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", "dev": true }, - "node_modules/serve-handler/node_modules/range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==", - "dev": true, - "engines": { - "node": ">= 0.6" - } + "node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha1-fpWsskqpL1iF4KvvW6ExMw1K5oM=", + "dev": true }, - "node_modules/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha1-N6XPC4HsvGlD3hCbopYNGyZYSuc=", "dev": true, "dependencies": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" }, - "engines": { - "node": ">= 0.8.0" + "bin": { + "sha.js": "bin.js" } }, - "node_modules/serve-index/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" + "shebang-regex": "^1.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "node_modules/shebang-loader": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/shebang-loader/-/shebang-loader-0.0.1.tgz", + "integrity": "sha1-pAAEldRMzu++xjQ157FphWn6Uuw=", "dev": true }, - "node_modules/serve-index/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY=", + "node_modules/shell-quote": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", + "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", + "dev": true, + "dependencies": { + "array-filter": "~0.0.0", + "array-map": "~0.0.0", + "array-reduce": "~0.0.0", + "jsonify": "~0.0.0" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, - "node_modules/serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha1-Zm5jbcTwEPfvKZcKiKZ0MgiYsvk=", + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", "dev": true, "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - }, - "engines": { - "node": ">= 0.8.0" + "is-arrayish": "^0.3.1" } }, - "node_modules/serve/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha1-RXSirlb3qyBolvtDHq7tBm/fjwM=", + "dev": true + }, + "node_modules/single-line-log": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-1.1.2.tgz", + "integrity": "sha1-wvg/Jzo+GhbtsJlWYdoO1e8DM2Q=", "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "string-width": "^1.0.1" } }, - "node_modules/serve/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "node_modules/single-line-log/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/serve/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "node_modules/single-line-log/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, - "engines": { - "node": ">=12" + "dependencies": { + "number-is-nan": "^1.0.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/serve/node_modules/boxen": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.0.0.tgz", - "integrity": "sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg==", + "node_modules/single-line-log/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "dependencies": { - "ansi-align": "^3.0.1", - "camelcase": "^7.0.0", - "chalk": "^5.0.1", - "cli-boxes": "^3.0.0", - "string-width": "^5.1.2", - "type-fest": "^2.13.0", - "widest-line": "^4.0.1", - "wrap-ansi": "^8.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" }, "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/serve/node_modules/camelcase": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", - "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", + "node_modules/single-line-log/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, - "engines": { - "node": ">=14.16" + "dependencies": { + "ansi-regex": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/serve/node_modules/chalk": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.1.tgz", - "integrity": "sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==", + "node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha1-3lUoUaF1nfOo8gZTVEL17E3eq0Q=", "dev": true, "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=6" } }, - "node_modules/serve/node_modules/cli-boxes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "node_modules/slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha1-BE8aSdiEL/MHqta1Be0Xi9lQE00=", "dev": true, - "engines": { - "node": ">=10" + "optional": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=4" } }, - "node_modules/serve/node_modules/clipboardy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-3.0.0.tgz", - "integrity": "sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==", + "node_modules/snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=", "dev": true, "dependencies": { - "arch": "^2.2.0", - "execa": "^5.1.1", - "is-wsl": "^2.2.0" + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/serve/node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "node_modules/snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", "dev": true, "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" }, "engines": { - "node": ">= 8" + "node": ">=0.10.0" } }, - "node_modules/serve/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/serve/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/serve/node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/serve/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/serve/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/serve/node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "dependencies": { - "is-docker": "^2.0.0" + "is-descriptor": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/serve/node_modules/json-schema-traverse": { + "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/serve/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/serve/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/serve/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/serve/node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/serve/node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "dependencies": { - "shebang-regex": "^3.0.0" + "kind-of": "^6.0.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/serve/node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/serve/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "node_modules/snapdragon-node/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "kind-of": "^6.0.0" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/serve/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "node_modules/snapdragon-node/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/serve/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true, "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/serve/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "node_modules/snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", "dev": true, "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" + "kind-of": "^3.2.0" }, "engines": { - "node": ">= 8" + "node": ">=0.10.0" } }, - "node_modules/serve/node_modules/widest-line": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", - "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "dependencies": { - "string-width": "^5.0.1" + "is-buffer": "^1.1.5" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/serve/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "node_modules/snapdragon/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "node_modules/set-immediate-shim": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", - "dev": true, - "engines": { - "node": ">=0.10.0" + "ms": "2.0.0" } }, - "node_modules/set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha1-oY1AUw5vB95CKMfe/kInr4ytAFs=", + "node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "dependencies": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" + "is-descriptor": "^0.1.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/set-value/node_modules/extend-shallow": { + "node_modules/snapdragon/node_modules/extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", @@ -14139,1270 +13773,1353 @@ "node": ">=0.10.0" } }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "node_modules/setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha1-fpWsskqpL1iF4KvvW6ExMw1K5oM=", + "node_modules/snapdragon/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha1-N6XPC4HsvGlD3hCbopYNGyZYSuc=", - "dev": true, + "node_modules/socket.io": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.2.0.tgz", + "integrity": "sha512-wxXrIuZ8AILcn+f1B4ez4hJTPG24iNgxBBDaJfT6MsyOhVYiTXWexGoPkd87ktJG8kQEcL/NBvRi64+9k4Kc0w==", "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" + "debug": "~4.1.0", + "engine.io": "~3.3.1", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.2.0", + "socket.io-parser": "~3.3.0" } }, - "node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, + "node_modules/socket.io-adapter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", + "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=" + }, + "node_modules/socket.io-client": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.2.0.tgz", + "integrity": "sha512-56ZrkTDbdTLmBIyfFYesgOxsjcLnwAKoN4CiPyTVkMQj3zTUh0QAx3GbvIvLpFEOvQWu92yyWICxB0u7wkVbYA==", "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "engine.io-client": "~3.3.1", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.3.0", + "to-array": "0.1.4" } }, - "node_modules/shebang-loader": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/shebang-loader/-/shebang-loader-0.0.1.tgz", - "integrity": "sha1-pAAEldRMzu++xjQ157FphWn6Uuw=", - "dev": true - }, - "node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/socket.io-client/node_modules/component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" }, - "node_modules/shell-quote": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", - "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", - "dev": true, + "node_modules/socket.io-client/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dependencies": { - "array-filter": "~0.0.0", - "array-map": "~0.0.0", - "array-reduce": "~0.0.0", - "jsonify": "~0.0.0" + "ms": "2.0.0" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "node_modules/socket.io-client/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, - "node_modules/simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", - "dev": true, + "node_modules/socket.io-parser": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz", + "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==", "dependencies": { - "is-arrayish": "^0.3.1" + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" } }, - "node_modules/simple-swizzle/node_modules/is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha1-RXSirlb3qyBolvtDHq7tBm/fjwM=", - "dev": true + "node_modules/socket.io-parser/node_modules/component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" }, - "node_modules/single-line-log": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-1.1.2.tgz", - "integrity": "sha1-wvg/Jzo+GhbtsJlWYdoO1e8DM2Q=", - "dev": true, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dependencies": { - "string-width": "^1.0.1" + "ms": "2.0.0" } }, - "node_modules/single-line-log/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "node_modules/socket.io-parser/node_modules/isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" + }, + "node_modules/socket.io-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/sockjs": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", + "integrity": "sha1-2Xa76ACve9IK4IWY1YI5NQiZPA0=", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "faye-websocket": "^0.10.0", + "uuid": "^3.0.1" } }, - "node_modules/single-line-log/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "node_modules/sockjs-client": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.3.0.tgz", + "integrity": "sha1-EvydbLZj2lc509xftuhofalcsXc=", "dev": true, "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" + "debug": "^3.2.5", + "eventsource": "^1.0.7", + "faye-websocket": "~0.11.1", + "inherits": "^2.0.3", + "json3": "^3.3.2", + "url-parse": "^1.4.3" } }, - "node_modules/single-line-log/node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "node_modules/sockjs-client/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", "dev": true, "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" + "ms": "^2.1.1" } }, - "node_modules/single-line-log/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "node_modules/sockjs-client/node_modules/faye-websocket": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", + "integrity": "sha1-XA6aiWjokSwoZjn96XeosgnyUI4=", "dev": true, "dependencies": { - "ansi-regex": "^2.0.0" + "websocket-driver": ">=0.5.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=0.8.0" } }, - "node_modules/slash": { + "node_modules/sort-keys": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha1-3lUoUaF1nfOo8gZTVEL17E3eq0Q=", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/slice-ansi": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha1-BE8aSdiEL/MHqta1Be0Xi9lQE00=", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", "dev": true, - "optional": true, "dependencies": { - "is-fullwidth-code-point": "^2.0.0" + "is-plain-obj": "^1.0.0" }, "engines": { "node": ">=4" } }, - "node_modules/snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=", + "node_modules/source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha1-OZO9hzv8SEecyp6jpUeDXHwVSzQ=", + "dev": true + }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true, - "dependencies": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, "engines": { "node": ">=0.10.0" } }, - "node_modules/snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", + "node_modules/source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha1-cuLMNAlVQ+Q7LGKyxMENSpBU8lk=", + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", "dev": true, "dependencies": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" } }, - "node_modules/snapdragon-node/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "node_modules/source-map-support": { + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", + "integrity": "sha1-tPOxDVGFelrwE4086AA7IBYT1Zk=", "dev": true, "dependencies": { - "is-descriptor": "^1.0.0" - }, + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "node_modules/source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "deprecated": "See https://github.com/lydell/source-map-url#deprecated", + "dev": true + }, + "node_modules/spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha1-+4PlBERSaPFUsHTiGMh8ADzTHfQ=", "dev": true, "dependencies": { - "kind-of": "^6.0.0" + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha1-LqRQrudPKom/uUUZwH/Nb0EyKXc=", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha1-meEZt6XaAOBUkcn6M4t5BII7QdA=", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha1-NpS1gEVnpFjTyARYQqY1hjL2JlQ=", + "dev": true + }, + "node_modules/spdy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.0.tgz", + "integrity": "sha1-gfIitadDoymqEs6mo5DmDpthPFI=", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=6.0.0", + "npm": ">=6.0.0" } }, - "node_modules/snapdragon-node/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha1-ANSGOmQArXXfkzYaFghgXl3NzzE=", "dev": true, "dependencies": { - "kind-of": "^6.0.0" + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/spdy-transport/node_modules/readable-stream": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", + "integrity": "sha1-pRwmdUZY4KPCHb9ZFjvUW6b0R/w=", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, - "node_modules/snapdragon-node/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "node_modules/spectron": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/spectron/-/spectron-7.0.0.tgz", + "integrity": "sha1-KhbqKy++YUn1+p+hor5gH1h44Aw=", "dev": true, "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "dev-null": "^0.1.1", + "electron-chromedriver": "^5.0.1", + "request": "^2.87.0", + "split": "^1.0.0", + "webdriverio": "^4.13.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=0.12.4" } }, - "node_modules/snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", + "node_modules/speedometer": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz", + "integrity": "sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=", + "dev": true + }, + "node_modules/split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha1-YFvZvjA6pZ+zX5Ip++oN3snqB9k=", "dev": true, "dependencies": { - "kind-of": "^3.2.0" + "through": "2" }, "engines": { - "node": ">=0.10.0" + "node": "*" } }, - "node_modules/snapdragon-util/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", "dev": true, "dependencies": { - "is-buffer": "^1.1.5" + "extend-shallow": "^3.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/snapdragon/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "node_modules/split2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.1.1.tgz", + "integrity": "sha1-xR8Y8+BqjERpqqtIdofY2VYWC7Y=", "dev": true, "dependencies": { - "ms": "2.0.0" + "readable-stream": "^3.0.0" } }, - "node_modules/snapdragon/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "node_modules/split2/node_modules/readable-stream": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", + "integrity": "sha1-pRwmdUZY4KPCHb9ZFjvUW6b0R/w=", "dev": true, "dependencies": { - "is-descriptor": "^0.1.0" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, - "node_modules/snapdragon/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha1-+2YcC+8ps520B2nuOfpwCT1vaHc=", "dev": true, "dependencies": { - "is-extendable": "^0.1.0" + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/snapdragon/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/socket.io": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.2.0.tgz", - "integrity": "sha512-wxXrIuZ8AILcn+f1B4ez4hJTPG24iNgxBBDaJfT6MsyOhVYiTXWexGoPkd87ktJG8kQEcL/NBvRi64+9k4Kc0w==", + "node_modules/ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha1-KjxBso3UW2K2Nnbst0ABJlrp7dg=", + "dev": true, "dependencies": { - "debug": "~4.1.0", - "engine.io": "~3.3.1", - "has-binary2": "~1.0.2", - "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.2.0", - "socket.io-parser": "~3.3.0" + "figgy-pudding": "^3.5.1" } }, - "node_modules/socket.io-adapter": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", - "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=" + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha1-g26zyDgv4pNv6vVEYxAXzn1Ho88=", + "dev": true }, - "node_modules/socket.io-client": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.2.0.tgz", - "integrity": "sha512-56ZrkTDbdTLmBIyfFYesgOxsjcLnwAKoN4CiPyTVkMQj3zTUh0QAx3GbvIvLpFEOvQWu92yyWICxB0u7wkVbYA==", - "dependencies": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "engine.io-client": "~3.3.1", - "has-binary2": "~1.0.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "~3.3.0", - "to-array": "0.1.4" - } - }, - "node_modules/socket.io-client/node_modules/component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" - }, - "node_modules/socket.io-client/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dependencies": { - "ms": "2.0.0" - } + "node_modules/stackframe": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.0.4.tgz", + "integrity": "sha1-NXskqZL5Qny6a1RdlqFO0svKGHs=", + "dev": true }, - "node_modules/socket.io-client/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "node_modules/stat-mode": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.3.0.tgz", + "integrity": "sha1-aSg7CB+FFYKzKNKkrOX1kc5S9Us=", + "dev": true }, - "node_modules/socket.io-parser": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz", - "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==", + "node_modules/static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, "dependencies": { - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "isarray": "2.0.1" + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/socket.io-parser/node_modules/component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" - }, - "node_modules/socket.io-parser/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, "dependencies": { - "ms": "2.0.0" + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/socket.io-parser/node_modules/isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" - }, - "node_modules/socket.io-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/sockjs": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", - "integrity": "sha1-2Xa76ACve9IK4IWY1YI5NQiZPA0=", + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", "dev": true, - "dependencies": { - "faye-websocket": "^0.10.0", - "uuid": "^3.0.1" + "engines": { + "node": ">= 0.6" } }, - "node_modules/sockjs-client": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.3.0.tgz", - "integrity": "sha1-EvydbLZj2lc509xftuhofalcsXc=", + "node_modules/stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", "dev": true, - "dependencies": { - "debug": "^3.2.5", - "eventsource": "^1.0.7", - "faye-websocket": "~0.11.1", - "inherits": "^2.0.3", - "json3": "^3.3.2", - "url-parse": "^1.4.3" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/sockjs-client/node_modules/debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "node_modules/stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha1-h1IdOKRKp+6RzhzSpH3wy0ndZgs=", "dev": true, "dependencies": { - "ms": "^2.1.1" + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" } }, - "node_modules/sockjs-client/node_modules/faye-websocket": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", - "integrity": "sha1-XA6aiWjokSwoZjn96XeosgnyUI4=", + "node_modules/stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha1-6+J6DDibBPvMIzZClS4Qcxr6m64=", "dev": true, "dependencies": { - "websocket-driver": ">=0.5.1" - }, - "engines": { - "node": ">=0.8.0" + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" } }, - "node_modules/sort-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", - "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "node_modules/stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha1-stJCRpKIpaJ+xP6JM6z2I95lFPw=", "dev": true, "dependencies": { - "is-plain-obj": "^1.0.0" - }, - "engines": { - "node": ">=4" + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" } }, - "node_modules/source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha1-OZO9hzv8SEecyp6jpUeDXHwVSzQ=", + "node_modules/stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", "dev": true }, - "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "node_modules/strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha1-cuLMNAlVQ+Q7LGKyxMENSpBU8lk=", - "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "dependencies": { - "atob": "^2.1.1", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" + "safe-buffer": "~5.1.0" } }, - "node_modules/source-map-support": { - "version": "0.5.12", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", - "integrity": "sha1-tPOxDVGFelrwE4086AA7IBYT1Zk=", + "node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", "dev": true, "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "node_modules/string-width/node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "deprecated": "See https://github.com/lydell/source-map-url#deprecated", - "dev": true - }, - "node_modules/spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha1-+4PlBERSaPFUsHTiGMh8ADzTHfQ=", + "node_modules/string-width/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha1-LqRQrudPKom/uUUZwH/Nb0EyKXc=", - "dev": true - }, - "node_modules/spdx-expression-parse": { + "node_modules/string.prototype.padend": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha1-meEZt6XaAOBUkcn6M4t5BII7QdA=", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz", + "integrity": "sha1-86rvfBcZ8XDF6rHDK/eA2W4h8vA=", "dev": true, "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "define-properties": "^1.1.2", + "es-abstract": "^1.4.3", + "function-bind": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" } }, - "node_modules/spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha1-NpS1gEVnpFjTyARYQqY1hjL2JlQ=", - "dev": true - }, - "node_modules/spdy": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.0.tgz", - "integrity": "sha1-gfIitadDoymqEs6mo5DmDpthPFI=", + "node_modules/string.prototype.padstart": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.padstart/-/string.prototype.padstart-3.0.0.tgz", + "integrity": "sha1-W8+tOfRkm7LQMSkuGbzwtRDUskI=", "dev": true, "dependencies": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" + "define-properties": "^1.1.2", + "es-abstract": "^1.4.3", + "function-bind": "^1.0.2" }, "engines": { - "node": ">=6.0.0", - "npm": ">=6.0.0" + "node": ">= 0.4" } }, - "node_modules/spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha1-ANSGOmQArXXfkzYaFghgXl3NzzE=", + "node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4=", "dev": true, "dependencies": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/spdy-transport/node_modules/readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha1-pRwmdUZY4KPCHb9ZFjvUW6b0R/w=", + "node_modules/strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "is-utf8": "^0.2.0" }, "engines": { - "node": ">= 6" + "node": ">=0.10.0" } }, - "node_modules/spectron": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/spectron/-/spectron-7.0.0.tgz", - "integrity": "sha1-KhbqKy++YUn1+p+hor5gH1h44Aw=", + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true, - "dependencies": { - "dev-null": "^0.1.1", - "electron-chromedriver": "^5.0.1", - "request": "^2.87.0", - "split": "^1.0.0", - "webdriverio": "^4.13.0" - }, "engines": { - "node": ">=0.12.4" + "node": ">=0.10.0" } }, - "node_modules/speedometer": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz", - "integrity": "sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=", - "dev": true + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } }, - "node_modules/split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha1-YFvZvjA6pZ+zX5Ip++oN3snqB9k=", + "node_modules/strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", "dev": true, - "dependencies": { - "through": "2" - }, "engines": { - "node": "*" + "node": ">=4" } }, - "node_modules/split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, - "dependencies": { - "extend-shallow": "^3.0.0" - }, "engines": { "node": ">=0.10.0" } }, - "node_modules/split2": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.1.1.tgz", - "integrity": "sha1-xR8Y8+BqjERpqqtIdofY2VYWC7Y=", + "node_modules/stylehacks": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", + "integrity": "sha1-Zxj8r00eB9ihMYaQiB6NlnJqcdU=", "dev": true, "dependencies": { - "readable-stream": "^3.0.0" + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/split2/node_modules/readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha1-pRwmdUZY4KPCHb9ZFjvUW6b0R/w=", + "node_modules/stylehacks/node_modules/postcss-selector-parser": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", + "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", "dev": true, "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "dot-prop": "^4.1.1", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" }, "engines": { - "node": ">= 6" + "node": ">=4" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "node_modules/sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha1-+2YcC+8ps520B2nuOfpwCT1vaHc=", + "node_modules/sumchecker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-2.0.2.tgz", + "integrity": "sha1-D0LBDl0F2l1C7qPlbDOZo31sWz4=", "dev": true, "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" + "debug": "^2.2.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 4.0" } }, - "node_modules/ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha1-KjxBso3UW2K2Nnbst0ABJlrp7dg=", + "node_modules/sumchecker/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "dependencies": { - "figgy-pudding": "^3.5.1" + "ms": "2.0.0" } }, - "node_modules/stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha1-g26zyDgv4pNv6vVEYxAXzn1Ho88=", - "dev": true - }, - "node_modules/stackframe": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.0.4.tgz", - "integrity": "sha1-NXskqZL5Qny6a1RdlqFO0svKGHs=", - "dev": true - }, - "node_modules/stat-mode": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.3.0.tgz", - "integrity": "sha1-aSg7CB+FFYKzKNKkrOX1kc5S9Us=", + "node_modules/sumchecker/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, - "node_modules/static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=", "dev": true, "dependencies": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" + "has-flag": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/static-extend/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "node_modules/svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=", + "dev": true + }, + "node_modules/svgo": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.0.tgz", + "integrity": "sha1-uuUbqV3tmjOja3xGzpw1mukVQxM=", + "deprecated": "This SVGO version is no longer supported. Upgrade to v2.x.x.", "dev": true, "dependencies": { - "is-descriptor": "^0.1.0" + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.33", + "csso": "^3.5.1", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + }, + "bin": { + "svgo": "bin/svgo" }, "engines": { - "node": ">=0.10.0" + "node": ">=4.0.0" } }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "node_modules/table": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha1-ozRHN1OR52atNNNIbm4q7chNLjY=", "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/stealthy-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", - "dev": true, - "engines": { - "node": ">=0.10.0" + "optional": true, + "dependencies": { + "ajv": "^5.2.3", + "ajv-keywords": "^2.1.0", + "chalk": "^2.1.0", + "lodash": "^4.17.4", + "slice-ansi": "1.0.0", + "string-width": "^2.1.1" } }, - "node_modules/stream-browserify": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", - "integrity": "sha1-h1IdOKRKp+6RzhzSpH3wy0ndZgs=", + "node_modules/table/node_modules/ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "dev": true, + "optional": true, "dependencies": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" } }, - "node_modules/stream-each": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", - "integrity": "sha1-6+J6DDibBPvMIzZClS4Qcxr6m64=", + "node_modules/table/node_modules/ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" + "optional": true, + "peerDependencies": { + "ajv": "^5.0.0" } }, - "node_modules/stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha1-stJCRpKIpaJ+xP6JM6z2I95lFPw=", + "node_modules/table/node_modules/fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true, - "dependencies": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - } + "optional": true }, - "node_modules/stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", - "dev": true + "node_modules/table/node_modules/json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true, + "optional": true }, - "node_modules/strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "node_modules/tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha1-ofzMBrWNth/XpF2i2kT186Pme6I=", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "node_modules/tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha1-jqVdqzeXIlPZqa+Q/c1VmuQ1xVU=", "dev": true, "dependencies": { - "safe-buffer": "~5.1.0" + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", + "node_modules/temp-file": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.3.4.tgz", + "integrity": "sha1-c6+GjNfLdACkTkuwPmU7IoDOKHg=", "dev": true, "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "async-exit-hook": "^2.0.1", + "fs-extra": "^8.1.0" + } + }, + "node_modules/temp-file/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha1-SdQ8RaiM2Wd2aMt74bRu/bjS4cA=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" }, "engines": { - "node": ">=4" + "node": ">=6 <7 || >=8" } }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "node_modules/term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", "dev": true, + "dependencies": { + "execa": "^0.7.0" + }, "engines": { "node": ">=4" } }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "node_modules/term-size/node_modules/cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "dependencies": { - "ansi-regex": "^3.0.0" + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "node_modules/term-size/node_modules/execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "dependencies": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" }, "engines": { "node": ">=4" } }, - "node_modules/string.prototype.padend": { + "node_modules/term-size/node_modules/get-stream": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz", - "integrity": "sha1-86rvfBcZ8XDF6rHDK/eA2W4h8vA=", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true, - "dependencies": { - "define-properties": "^1.1.2", - "es-abstract": "^1.4.3", - "function-bind": "^1.0.2" - }, "engines": { - "node": ">= 0.4" + "node": ">=4" } }, - "node_modules/string.prototype.padstart": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/string.prototype.padstart/-/string.prototype.padstart-3.0.0.tgz", - "integrity": "sha1-W8+tOfRkm7LQMSkuGbzwtRDUskI=", + "node_modules/term-size/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=", "dev": true, "dependencies": { - "define-properties": "^1.1.2", - "es-abstract": "^1.4.3", - "function-bind": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" } }, - "node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4=", + "node_modules/term-size/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "node_modules/terser": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.1.2.tgz", + "integrity": "sha1-smVsilBvfOgFo/MAov9I2wIvo5E=", "dev": true, "dependencies": { - "ansi-regex": "^4.1.0" + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "bin": { + "terser": "bin/uglifyjs" }, "engines": { - "node": ">=6" + "node": ">=6.0.0" } }, - "node_modules/strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "node_modules/terser-webpack-plugin": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.3.0.tgz", + "integrity": "sha1-aaoiQmKZ9LWzd1y+2MssXUGaodQ=", "dev": true, "dependencies": { - "is-utf8": "^0.2.0" + "cacache": "^11.3.2", + "find-cache-dir": "^2.0.0", + "is-wsl": "^1.1.0", + "loader-utils": "^1.2.3", + "schema-utils": "^1.0.0", + "serialize-javascript": "^1.7.0", + "source-map": "^0.6.1", + "terser": "^4.0.0", + "webpack-sources": "^1.3.0", + "worker-farm": "^1.7.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^4.0.0" } }, - "node_modules/strip-eof": { + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 4" } }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "node_modules/terser-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/strip-indent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", - "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", + "node_modules/terser/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/thenify": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz", + "integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "any-promise": "^1.0.0" } }, - "node_modules/stylehacks": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", - "integrity": "sha1-Zxj8r00eB9ihMYaQiB6NlnJqcdU=", + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", "dev": true, "dependencies": { - "browserslist": "^4.0.0", - "postcss": "^7.0.0", - "postcss-selector-parser": "^3.0.0" + "thenify": ">= 3.1.0 < 4" }, "engines": { - "node": ">=6.9.0" + "node": ">=0.8" } }, - "node_modules/stylehacks/node_modules/postcss-selector-parser": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", - "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", + "node_modules/thread-loader": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/thread-loader/-/thread-loader-2.1.2.tgz", + "integrity": "sha1-9YXdOOhSx/nN7V0JKZIQgUj16zA=", "dev": true, "dependencies": { - "dot-prop": "^4.1.1", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" + "loader-runner": "^2.3.1", + "loader-utils": "^1.1.0", + "neo-async": "^2.6.0" }, "engines": { - "node": ">=4" + "node": ">= 6.9.0 <7.0.0 || >= 8.9.0" + }, + "peerDependencies": { + "webpack": "^2.0.0 || ^3.0.0 || ^4.0.0" } }, - "node_modules/sumchecker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-2.0.2.tgz", - "integrity": "sha1-D0LBDl0F2l1C7qPlbDOZo31sWz4=", + "node_modules/throttleit": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", + "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=", + "dev": true + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha1-AcHjnrMdB8t9A6lqcIIyYLIxMs0=", "dev": true, "dependencies": { - "debug": "^2.2.0" - }, - "engines": { - "node": ">= 4.0" + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" } }, - "node_modules/sumchecker/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "node_modules/through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha1-cA54bfI2fCyIzYqlvkz5weeDElQ=", "dev": true, "dependencies": { - "ms": "2.0.0" + "through2": "~2.0.0", + "xtend": "~4.0.0" } }, - "node_modules/sumchecker/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "node_modules/through2-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-map/-/through2-map-3.0.0.tgz", + "integrity": "sha1-psMCbOY7SJipl9VAUGtm/9lw8nE=", + "dev": true, + "dependencies": { + "through2": "~2.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/thunky": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz", + "integrity": "sha1-9d9zJFNAewkZHa5z4qjMc/OBqCY=", "dev": true }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=", + "node_modules/timers-browserify": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", + "integrity": "sha1-HSjj0qrfHVpZlsTp+VYBzQU0gK4=", "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "setimmediate": "^1.0.4" }, "engines": { - "node": ">=4" + "node": ">=0.6.0" } }, - "node_modules/svg-tags": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", - "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=", + "node_modules/timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", "dev": true }, - "node_modules/svgo": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.0.tgz", - "integrity": "sha1-uuUbqV3tmjOja3xGzpw1mukVQxM=", - "deprecated": "This SVGO version is no longer supported. Upgrade to v2.x.x.", + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", "dev": true, "dependencies": { - "chalk": "^2.4.1", - "coa": "^2.0.2", - "css-select": "^2.0.0", - "css-select-base-adapter": "^0.1.1", - "css-tree": "1.0.0-alpha.33", - "csso": "^3.5.1", - "js-yaml": "^3.13.1", - "mkdirp": "~0.5.1", - "object.values": "^1.1.0", - "sax": "~1.2.4", - "stable": "^0.1.8", - "unquote": "~1.1.1", - "util.promisify": "~1.0.0" - }, - "bin": { - "svgo": "bin/svgo" + "os-tmpdir": "~1.0.2" }, "engines": { - "node": ">=4.0.0" + "node": ">=0.6.0" } }, - "node_modules/table": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", - "integrity": "sha1-ozRHN1OR52atNNNIbm4q7chNLjY=", + "node_modules/to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" + }, + "node_modules/to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "node_modules/to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha1-STvUj2LXxD/N7TE6A9ytsuEhOoA=", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", "dev": true, - "optional": true, - "dependencies": { - "ajv": "^5.2.3", - "ajv-keywords": "^2.1.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", - "slice-ansi": "1.0.0", - "string-width": "^2.1.1" + "engines": { + "node": ">=4" } }, - "node_modules/table/node_modules/ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "node_modules/to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, - "optional": true, "dependencies": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/table/node_modules/ajv-keywords": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", - "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, - "optional": true, - "peerDependencies": { - "ajv": "^5.0.0" + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/table/node_modules/fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "node_modules/to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha1-zgqgwvPfat+FLvtASng+d8BHV3E=", "dev": true, - "optional": true + "engines": { + "node": ">=6" + } }, - "node_modules/table/node_modules/json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true, - "optional": true - }, - "node_modules/tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha1-ofzMBrWNth/XpF2i2kT186Pme6I=", + "node_modules/to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=", "dev": true, + "dependencies": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/tar-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", - "integrity": "sha1-jqVdqzeXIlPZqa+Q/c1VmuQ1xVU=", + "node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, "dependencies": { - "bl": "^1.0.0", - "buffer-alloc": "^1.2.0", - "end-of-stream": "^1.0.0", - "fs-constants": "^1.0.0", - "readable-stream": "^2.3.0", - "to-buffer": "^1.1.1", - "xtend": "^4.0.0" + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" }, "engines": { - "node": ">= 0.8.0" + "node": ">=0.10.0" } }, - "node_modules/temp-file": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.3.4.tgz", - "integrity": "sha1-c6+GjNfLdACkTkuwPmU7IoDOKHg=", + "node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha1-fhvjRw8ed5SLxD2Uo8j013UrpVM=", "dev": true, - "dependencies": { - "async-exit-hook": "^2.0.1", - "fs-extra": "^8.1.0" + "engines": { + "node": ">=0.6" } }, - "node_modules/temp-file/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha1-SdQ8RaiM2Wd2aMt74bRu/bjS4cA=", + "node_modules/toposort": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz", + "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=", + "dev": true + }, + "node_modules/tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha1-U/Nto/R3g7CSWvoG/587FlKA94E=", "dev": true, "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "psl": "^1.1.24", + "punycode": "^1.4.1" }, "engines": { - "node": ">=6 <7 || >=8" + "node": ">=0.8" } }, - "node_modules/term-size": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", - "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "node_modules/tough-cookie/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "node_modules/trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", "dev": true, - "dependencies": { - "execa": "^0.7.0" - }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/term-size/node_modules/cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "node_modules/trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true, - "dependencies": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/term-size/node_modules/execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "node_modules/truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha1-QFkjkJWS1W94pYGENLC3hInKXys=", "dev": true, "dependencies": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=4" + "utf8-byte-length": "^1.0.1" } }, - "node_modules/term-size/node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true, - "engines": { - "node": ">=4" - } + "node_modules/tryer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", + "integrity": "sha1-8shUBoALmw90yfdGW4HqrSQSUvg=", + "dev": true }, - "node_modules/term-size/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=", + "node_modules/tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha1-w8GflZc/sKYpc/sJ2Q2WHuQ+XIo=", + "dev": true + }, + "node_modules/tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" } }, - "node_modules/term-size/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, - "node_modules/terser": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.1.2.tgz", - "integrity": "sha1-smVsilBvfOgFo/MAov9I2wIvo5E=", + "node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "dependencies": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - }, - "bin": { - "terser": "bin/uglifyjs" + "prelude-ls": "~1.1.2" }, "engines": { - "node": ">=6.0.0" + "node": ">= 0.8.0" } }, - "node_modules/terser-webpack-plugin": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.3.0.tgz", - "integrity": "sha1-aaoiQmKZ9LWzd1y+2MssXUGaodQ=", + "node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha1-jSojcNPfiG61yQraHFv2GIrPg4s=", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha1-TlUs0F3wlGfcvE73Od6J8s83wTE=", "dev": true, "dependencies": { - "cacache": "^11.3.2", - "find-cache-dir": "^2.0.0", - "is-wsl": "^1.1.0", - "loader-utils": "^1.2.3", - "schema-utils": "^1.0.0", - "serialize-javascript": "^1.7.0", - "source-map": "^0.6.1", - "terser": "^4.0.0", - "webpack-sources": "^1.3.0", - "worker-farm": "^1.7.0" + "media-typer": "0.3.0", + "mime-types": "~2.1.24" }, "engines": { - "node": ">= 6.9.0" - }, - "peerDependencies": { - "webpack": "^4.0.0" + "node": ">= 0.6" } }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "node_modules/uglify-js": { + "version": "3.4.10", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", + "integrity": "sha1-mtlWPY6zrN+404WX0q8dgV9qdV8=", "dev": true, "dependencies": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" + "commander": "~2.19.0", + "source-map": "~0.6.1" + }, + "bin": { + "uglifyjs": "bin/uglifyjs" }, "engines": { - "node": ">= 4" + "node": ">=0.8.0" } }, - "node_modules/terser-webpack-plugin/node_modules/source-map": { + "node_modules/uglify-js/node_modules/commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha1-9hmKqE5bg8RgVLlN3tv+1e6f8So=", + "dev": true + }, + "node_modules/uglify-js/node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", @@ -15411,1402 +15128,1486 @@ "node": ">=0.10.0" } }, - "node_modules/terser/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "node_modules/ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha1-JhmADEyCWADv3YNDr33Zkzy+KBg=", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "node_modules/thenify": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz", - "integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=", + "node_modules/unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha1-jtKjJWmWG86SJ9Cc0/+7j+1fAgw=", "dev": true, "dependencies": { - "any-promise": "^1.0.0" + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + }, + "engines": { + "node": ">=4" } }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", + "node_modules/unicode-match-property-value-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz", + "integrity": "sha1-W0tCbgjROoA2Xg1lesemwexGonc=", "dev": true, - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, "engines": { - "node": ">=0.8" + "node": ">=4" } }, - "node_modules/thread-loader": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/thread-loader/-/thread-loader-2.1.2.tgz", - "integrity": "sha1-9YXdOOhSx/nN7V0JKZIQgUj16zA=", + "node_modules/unicode-property-aliases-ecmascript": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz", + "integrity": "sha1-qcxsx85joKMCP8meNBuUQx1AWlc=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha1-C2/nuDWuzaYcbqTU8CwUIh4QmEc=", "dev": true, "dependencies": { - "loader-runner": "^2.3.1", - "loader-utils": "^1.1.0", - "neo-async": "^2.6.0" + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" }, "engines": { - "node": ">= 6.9.0 <7.0.0 || >= 8.9.0" - }, - "peerDependencies": { - "webpack": "^2.0.0 || ^3.0.0 || ^4.0.0" + "node": ">=0.10.0" } }, - "node_modules/throttleit": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", - "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=", + "node_modules/uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", "dev": true }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "node_modules/uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", "dev": true }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha1-AcHjnrMdB8t9A6lqcIIyYLIxMs0=", + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha1-HWl2k2mtoFgxA6HmrodoG1ZXMjA=", "dev": true, "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "unique-slug": "^2.0.0" } }, - "node_modules/through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha1-cA54bfI2fCyIzYqlvkz5weeDElQ=", + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha1-uqvOkQg/xk6UWw861hPiZPfNTmw=", "dev": true, "dependencies": { - "through2": "~2.0.0", - "xtend": "~4.0.0" + "imurmurhash": "^0.1.4" } }, - "node_modules/through2-map": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-map/-/through2-map-3.0.0.tgz", - "integrity": "sha1-psMCbOY7SJipl9VAUGtm/9lw8nE=", + "node_modules/unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", "dev": true, "dependencies": { - "through2": "~2.0.0", - "xtend": "^4.0.0" + "crypto-random-string": "^1.0.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/thunky": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz", - "integrity": "sha1-9d9zJFNAewkZHa5z4qjMc/OBqCY=", - "dev": true - }, - "node_modules/timers-browserify": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", - "integrity": "sha1-HSjj0qrfHVpZlsTp+VYBzQU0gK4=", + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY=", "dev": true, - "dependencies": { - "setimmediate": "^1.0.4" - }, "engines": { - "node": ">=0.6.0" + "node": ">= 4.0.0" } }, - "node_modules/timsort": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", - "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", - "dev": true - }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", "dev": true, - "dependencies": { - "os-tmpdir": "~1.0.2" - }, "engines": { - "node": ">=0.6.0" + "node": ">= 0.8" } }, - "node_modules/to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" - }, - "node_modules/to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true - }, - "node_modules/to-buffer": { + "node_modules/unquote": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", - "integrity": "sha1-STvUj2LXxD/N7TE6A9ytsuEhOoA=", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", "dev": true }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "node_modules/unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "dev": true, + "dependencies": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, "dependencies": { - "kind-of": "^3.0.2" + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/to-object-path/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", "dev": true, "dependencies": { - "is-buffer": "^1.1.5" + "isarray": "1.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha1-zgqgwvPfat+FLvtASng+d8BHV3E=", + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", "dev": true, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=", + "node_modules/unzip-crx": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/unzip-crx/-/unzip-crx-0.2.0.tgz", + "integrity": "sha1-TAuqi9rHViVnVL7KeEPBPXuFjBg=", "dev": true, "dependencies": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" + "jszip": "^3.1.0", + "mkdirp": "^0.5.1", + "yaku": "^0.16.6" } }, - "node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "node_modules/upath": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", + "integrity": "sha1-PbZYYA7a7sy+bbXmhNZ+6MKs0Gg=", "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, "engines": { - "node": ">=0.10.0" + "node": ">=4", + "yarn": "*" } }, - "node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha1-fhvjRw8ed5SLxD2Uo8j013UrpVM=", + "node_modules/update-browserslist-db": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", + "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", "dev": true, - "engines": { - "node": ">=0.6" + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "node_modules/toposort": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz", - "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=", - "dev": true - }, - "node_modules/tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha1-U/Nto/R3g7CSWvoG/587FlKA94E=", + "node_modules/update-check": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/update-check/-/update-check-1.5.4.tgz", + "integrity": "sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==", "dev": true, "dependencies": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, - "engines": { - "node": ">=0.8" + "registry-auth-token": "3.3.2", + "registry-url": "3.1.0" } }, - "node_modules/tough-cookie/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "node_modules/trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "node_modules/update-check/node_modules/registry-auth-token": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" } }, - "node_modules/trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "node_modules/update-check/node_modules/registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==", "dev": true, + "dependencies": { + "rc": "^1.0.1" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/truncate-utf8-bytes": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", - "integrity": "sha1-QFkjkJWS1W94pYGENLC3hInKXys=", + "node_modules/update-notifier": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-3.0.1.tgz", + "integrity": "sha1-eOy2i5FeL9G+n3Z/bimM6HtzYlA=", "dev": true, "dependencies": { - "utf8-byte-length": "^1.0.1" + "boxen": "^3.0.0", + "chalk": "^2.0.1", + "configstore": "^4.0.0", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.1.0", + "is-npm": "^3.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.0.0", + "semver-diff": "^2.0.0", + "xdg-basedir": "^3.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/tryer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", - "integrity": "sha1-8shUBoALmw90yfdGW4HqrSQSUvg=", + "node_modules/update-notifier/node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha1-Z6npZL4xpR4V5QENWObxKDQAL0Y=", "dev": true }, - "node_modules/tslib": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", - "integrity": "sha1-w8GflZc/sKYpc/sJ2Q2WHuQ+XIo=", - "dev": true + "node_modules/update-notifier/node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha1-a8YzQYGBDgS1wis9WJ/cpVAmQEw=", + "dev": true, + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } }, - "node_modules/tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "node_modules/upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", "dev": true }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "node_modules/uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha1-lMVA4f93KVbiKZUHwBCupsiDjrA=", "dev": true, "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" + "punycode": "^2.1.0" } }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "deprecated": "Please see https://github.com/lydell/urix#deprecated", "dev": true }, - "node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "node_modules/url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", "dev": true, "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" + "punycode": "1.3.2", + "querystring": "0.2.0" } }, - "node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha1-jSojcNPfiG61yQraHFv2GIrPg4s=", + "node_modules/url-loader": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-1.1.2.tgz", + "integrity": "sha1-uXHRkbg69pPF4/6kBkvp4fLX+Ng=", "dev": true, + "dependencies": { + "loader-utils": "^1.1.0", + "mime": "^2.0.3", + "schema-utils": "^1.0.0" + }, "engines": { - "node": ">=8" + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^3.0.0 || ^4.0.0" } }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha1-TlUs0F3wlGfcvE73Od6J8s83wTE=", + "node_modules/url-loader/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", "dev": true, "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" }, "engines": { - "node": ">= 0.6" + "node": ">= 4" } }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true + "node_modules/url-parse": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", + "integrity": "sha1-qKg1NejACjFuQDpdtKwbm4U64ng=", + "dev": true, + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } }, - "node_modules/uglify-js": { - "version": "3.4.10", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", - "integrity": "sha1-mtlWPY6zrN+404WX0q8dgV9qdV8=", + "node_modules/url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", "dev": true, "dependencies": { - "commander": "~2.19.0", - "source-map": "~0.6.1" - }, - "bin": { - "uglifyjs": "bin/uglifyjs" + "prepend-http": "^2.0.0" }, "engines": { - "node": ">=0.8.0" + "node": ">=4" } }, - "node_modules/uglify-js/node_modules/commander": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", - "integrity": "sha1-9hmKqE5bg8RgVLlN3tv+1e6f8So=", + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", "dev": true }, - "node_modules/uglify-js/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "node_modules/use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha1-1QyMrHmhn7wg8pEfVuuXP04QBw8=", "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/ultron": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" - }, - "node_modules/unicode-canonical-property-names-ecmascript": { + "node_modules/utf8-byte-length": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", - "integrity": "sha1-JhmADEyCWADv3YNDr33Zkzy+KBg=", - "dev": true, - "engines": { - "node": ">=4" + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", + "integrity": "sha1-9F8VDExm7uloGGUFq5P8u4rWv2E=", + "dev": true + }, + "node_modules/util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha1-MjZzNyDsZLsn9uJvQhqqLhtYjWE=", + "dev": true, + "dependencies": { + "inherits": "2.0.3" } }, - "node_modules/unicode-match-property-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", - "integrity": "sha1-jtKjJWmWG86SJ9Cc0/+7j+1fAgw=", + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha1-RA9xZaRZyaFtwUXrjnLzVocJcDA=", "dev": true, "dependencies": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" - }, - "engines": { - "node": ">=4" + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" } }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz", - "integrity": "sha1-W0tCbgjROoA2Xg1lesemwexGonc=", + "node_modules/util/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", + "dev": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", "dev": true, "engines": { - "node": ">=4" + "node": ">= 0.4.0" } }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz", - "integrity": "sha1-qcxsx85joKMCP8meNBuUQx1AWlc=", + "node_modules/uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha1-G0r0lV6zB3xQHCOHL8ZROBFYcTE=", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", "dev": true, - "engines": { - "node": ">=4" + "bin": { + "uuid": "bin/uuid" } }, - "node_modules/union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha1-C2/nuDWuzaYcbqTU8CwUIh4QmEc=", + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha1-/JH2uce6FchX9MssXe/uw51PQQo=", "dev": true, "dependencies": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - }, + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, - "node_modules/uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "node_modules/vendors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.3.tgz", + "integrity": "sha1-pkZ3gavTZiF8BQ+CAuflDMnu+MA=", "dev": true }, - "node_modules/uniqs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", - "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/vm-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", + "integrity": "sha1-vXbWojMj4sqP+hICjcBFWcdfkBk=", "dev": true }, - "node_modules/unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha1-HWl2k2mtoFgxA6HmrodoG1ZXMjA=", + "node_modules/vue": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.10.tgz", + "integrity": "sha1-pysaQqTYKnIepDjRtr9V5mGVxjc=" + }, + "node_modules/vue-cli-plugin-electron-builder": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/vue-cli-plugin-electron-builder/-/vue-cli-plugin-electron-builder-1.3.6.tgz", + "integrity": "sha1-mxhXtr4XX3Bo29H5BXU8ENfaRgc=", "dev": true, "dependencies": { - "unique-slug": "^2.0.0" + "chokidar": "^2.1.5", + "electron-builder": "^20.29.0", + "execa": "^1.0.0", + "friendly-errors-webpack-plugin": "^1.7.0", + "fs-extra": "^7.0.0", + "lodash.merge": "^4.6.1", + "portfinder": "^1.0.16", + "pumpify": "^1.5.1", + "semver": "^6.0.0", + "shebang-loader": "^0.0.1", + "spectron": "^7.0.0", + "split2": "^3.0.0", + "terser-webpack-plugin": "^1.1.0", + "through2-filter": "^3.0.0", + "through2-map": "^3.0.0", + "unzip-crx": "^0.2.0", + "webpack": "^4.18.0", + "webpack-chain": "^5.0.0", + "yargs": "^13.2.2" } }, - "node_modules/unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha1-uqvOkQg/xk6UWw861hPiZPfNTmw=", + "node_modules/vue-cli-plugin-electron-builder/node_modules/javascript-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.0.0.tgz", + "integrity": "sha1-73UCFq5mUE/9ZwtoyLiqB733tYg=", + "dev": true + }, + "node_modules/vue-cli-plugin-electron-builder/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/vue-cli-plugin-electron-builder/node_modules/webpack-chain": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-5.2.4.tgz", + "integrity": "sha1-zDZlopam7c2nODJFmRA6xuIV3aM=", "dev": true, "dependencies": { - "imurmurhash": "^0.1.4" + "deepmerge": "^1.5.2", + "javascript-stringify": "^2.0.0" } }, - "node_modules/unique-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", - "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "node_modules/vue-eslint-parser": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-2.0.3.tgz", + "integrity": "sha1-wmjJbG2Uz+PZOKX3WTlZsMozYNE=", "dev": true, + "optional": true, "dependencies": { - "crypto-random-string": "^1.0.0" + "debug": "^3.1.0", + "eslint-scope": "^3.7.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^3.5.2", + "esquery": "^1.0.0", + "lodash": "^4.17.4" }, "engines": { "node": ">=4" + }, + "peerDependencies": { + "eslint": ">=3.9.0" } }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY=", + "node_modules/vue-eslint-parser/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", "dev": true, - "engines": { - "node": ">= 4.0.0" + "optional": true, + "dependencies": { + "ms": "^2.1.1" } }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "node_modules/vue-eslint-parser/node_modules/eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha1-u1ByANPRf2AkdjYWC0gmKEsQhTU=", "dev": true, + "optional": true, + "dependencies": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + }, "engines": { - "node": ">= 0.8" + "node": ">=4.0.0" } }, - "node_modules/unquote": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", - "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", + "node_modules/vue-hot-reload-api": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.3.tgz", + "integrity": "sha1-J1b0bLMlgFTF9HI96K5+hzAqHM8=", "dev": true }, - "node_modules/unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "node_modules/vue-loader": { + "version": "15.7.1", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.7.1.tgz", + "integrity": "sha1-bMrNQSKqgPabqqwI/ylaYuOu/P0=", "dev": true, "dependencies": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" + "@vue/component-compiler-utils": "^3.0.0", + "hash-sum": "^1.0.2", + "loader-utils": "^1.1.0", + "vue-hot-reload-api": "^2.3.0", + "vue-style-loader": "^4.1.0" }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "peerDependencies": { + "css-loader": "*", + "webpack": "^4.1.0 || ^5.0.0-0" + } + }, + "node_modules/vue-loader/node_modules/@vue/component-compiler-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.0.0.tgz", + "integrity": "sha1-0W+ia4NsBt9bqutF89gK/EfjVjQ=", "dev": true, "dependencies": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" + "consolidate": "^0.15.1", + "hash-sum": "^1.0.2", + "lru-cache": "^4.1.2", + "merge-source-map": "^1.1.0", + "postcss": "^7.0.14", + "postcss-selector-parser": "^5.0.0", + "prettier": "1.16.3", + "source-map": "~0.6.1", + "vue-template-es2015-compiler": "^1.9.0" } }, - "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "node_modules/vue-loader/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=", "dev": true, "dependencies": { - "isarray": "1.0.0" - }, - "engines": { - "node": ">=0.10.0" + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" } }, - "node_modules/unset-value/node_modules/has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "node_modules/vue-loader/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/unzip-crx": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/unzip-crx/-/unzip-crx-0.2.0.tgz", - "integrity": "sha1-TAuqi9rHViVnVL7KeEPBPXuFjBg=", - "dev": true, - "dependencies": { - "jszip": "^3.1.0", - "mkdirp": "^0.5.1", - "yaku": "^0.16.6" - } + "node_modules/vue-loader/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true }, - "node_modules/upath": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", - "integrity": "sha1-PbZYYA7a7sy+bbXmhNZ+6MKs0Gg=", + "node_modules/vue-router": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.0.7.tgz", + "integrity": "sha1-s2yhB7SsuP9bxP+CRYQFnCP8uHs=" + }, + "node_modules/vue-style-loader": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz", + "integrity": "sha1-3t80mAbyXOtOZPOtfApE+6c1/Pg=", "dev": true, - "engines": { - "node": ">=4", - "yarn": "*" + "dependencies": { + "hash-sum": "^1.0.2", + "loader-utils": "^1.0.2" } }, - "node_modules/update-check": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/update-check/-/update-check-1.5.4.tgz", - "integrity": "sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==", + "node_modules/vue-template-compiler": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.10.tgz", + "integrity": "sha1-MjtPNJXwT6o1AzN6gvXWUHeZycw=", "dev": true, "dependencies": { - "registry-auth-token": "3.3.2", - "registry-url": "3.1.0" + "de-indent": "^1.0.2", + "he": "^1.1.0" } }, - "node_modules/update-check/node_modules/registry-auth-token": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", - "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "node_modules/vue-template-es2015-compiler": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz", + "integrity": "sha1-HuO8mhbsv1EYvjNLsV+cRvgvWCU=", + "dev": true + }, + "node_modules/watchpack": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", + "integrity": "sha1-S8EsLr6KonenHx0/FNaFx7RGzQA=", "dev": true, "dependencies": { - "rc": "^1.1.6", - "safe-buffer": "^5.0.1" + "chokidar": "^2.0.2", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" } }, - "node_modules/update-check/node_modules/registry-url": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", - "integrity": "sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==", + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha1-wdjRSTFtPqhShIiVy2oL/oh7h98=", "dev": true, "dependencies": { - "rc": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" + "minimalistic-assert": "^1.0.0" } }, - "node_modules/update-notifier": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-3.0.1.tgz", - "integrity": "sha1-eOy2i5FeL9G+n3Z/bimM6HtzYlA=", + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", "dev": true, "dependencies": { - "boxen": "^3.0.0", - "chalk": "^2.0.1", - "configstore": "^4.0.0", - "has-yarn": "^2.1.0", - "import-lazy": "^2.1.0", - "is-ci": "^2.0.0", - "is-installed-globally": "^0.1.0", - "is-npm": "^3.0.0", - "is-yarn-global": "^0.3.0", - "latest-version": "^5.0.0", - "semver-diff": "^2.0.0", - "xdg-basedir": "^3.0.0" - }, - "engines": { - "node": ">=8" + "defaults": "^1.0.3" } }, - "node_modules/update-notifier/node_modules/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha1-Z6npZL4xpR4V5QENWObxKDQAL0Y=", + "node_modules/wdio-dot-reporter": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/wdio-dot-reporter/-/wdio-dot-reporter-0.0.10.tgz", + "integrity": "sha1-+s+3ycWYQUmVH1nLw80HUhAc8OA=", "dev": true }, - "node_modules/update-notifier/node_modules/is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha1-a8YzQYGBDgS1wis9WJ/cpVAmQEw=", + "node_modules/webdriverio": { + "version": "4.14.4", + "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-4.14.4.tgz", + "integrity": "sha1-96lOmmUwgZeWCI9CsAmDPYPeA4Y=", + "deprecated": "outdated version, please use @next", "dev": true, "dependencies": { - "ci-info": "^2.0.0" + "archiver": "~2.1.0", + "babel-runtime": "^6.26.0", + "css-parse": "^2.0.0", + "css-value": "~0.0.1", + "deepmerge": "~2.0.1", + "ejs": "~2.5.6", + "gaze": "~1.1.2", + "glob": "~7.1.1", + "grapheme-splitter": "^1.0.2", + "inquirer": "~3.3.0", + "json-stringify-safe": "~5.0.1", + "mkdirp": "~0.5.1", + "npm-install-package": "~2.1.0", + "optimist": "~0.6.1", + "q": "~1.5.0", + "request": "^2.83.0", + "rgb2hex": "^0.1.9", + "safe-buffer": "~5.1.1", + "supports-color": "~5.0.0", + "url": "~0.11.0", + "wdio-dot-reporter": "~0.0.8", + "wgxpath": "~1.0.0" }, "bin": { - "is-ci": "bin.js" + "wdio": "bin/wdio" + }, + "engines": { + "node": ">= 4.8.5" } }, - "node_modules/upper-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", - "dev": true - }, - "node_modules/uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha1-lMVA4f93KVbiKZUHwBCupsiDjrA=", + "node_modules/webdriverio/node_modules/deepmerge": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.0.1.tgz", + "integrity": "sha1-JcHCTxEPuRT4AAG5JSZN138/QxI=", "dev": true, - "dependencies": { - "punycode": "^2.1.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "deprecated": "Please see https://github.com/lydell/urix#deprecated", - "dev": true + "node_modules/webdriverio/node_modules/ejs": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.9.tgz", + "integrity": "sha1-e6JUWCpWDSZ0NxCaaDVBEkdbDOU=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "node_modules/webdriverio/node_modules/has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", "dev": true, - "dependencies": { - "punycode": "1.3.2", - "querystring": "0.2.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/url-loader": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-1.1.2.tgz", - "integrity": "sha1-uXHRkbg69pPF4/6kBkvp4fLX+Ng=", + "node_modules/webdriverio/node_modules/supports-color": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.0.1.tgz", + "integrity": "sha1-HFMx8iJQyEICgFsvF63xZpnzo5o=", "dev": true, "dependencies": { - "loader-utils": "^1.1.0", - "mime": "^2.0.3", - "schema-utils": "^1.0.0" + "has-flag": "^2.0.0" }, "engines": { - "node": ">= 6.9.0" - }, - "peerDependencies": { - "webpack": "^3.0.0 || ^4.0.0" + "node": ">=4" } }, - "node_modules/url-loader/node_modules/schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", + "node_modules/webpack": { + "version": "4.28.4", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.28.4.tgz", + "integrity": "sha1-HdrmyJiH1++3Uq3ww80yubB+rNA=", "dev": true, "dependencies": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-module-context": "1.7.11", + "@webassemblyjs/wasm-edit": "1.7.11", + "@webassemblyjs/wasm-parser": "1.7.11", + "acorn": "^5.6.2", + "acorn-dynamic-import": "^3.0.0", "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" + "ajv-keywords": "^3.1.0", + "chrome-trace-event": "^1.0.0", + "enhanced-resolve": "^4.1.0", + "eslint-scope": "^4.0.0", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.3.0", + "loader-utils": "^1.1.0", + "memory-fs": "~0.4.1", + "micromatch": "^3.1.8", + "mkdirp": "~0.5.0", + "neo-async": "^2.5.0", + "node-libs-browser": "^2.0.0", + "schema-utils": "^0.4.4", + "tapable": "^1.1.0", + "terser-webpack-plugin": "^1.1.0", + "watchpack": "^1.5.0", + "webpack-sources": "^1.3.0" + }, + "bin": { + "webpack": "bin/webpack.js" }, "engines": { - "node": ">= 4" - } - }, - "node_modules/url-parse": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", - "integrity": "sha1-qKg1NejACjFuQDpdtKwbm4U64ng=", - "dev": true, - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" + "node": ">=6.11.5" } }, - "node_modules/url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "node_modules/webpack-bundle-analyzer": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.3.2.tgz", + "integrity": "sha1-PaczqQD1FZFOcp/OvNTEDd5x/G8=", "dev": true, "dependencies": { - "prepend-http": "^2.0.0" + "acorn": "^6.0.7", + "acorn-walk": "^6.1.1", + "bfj": "^6.1.1", + "chalk": "^2.4.1", + "commander": "^2.18.0", + "ejs": "^2.6.1", + "express": "^4.16.3", + "filesize": "^3.6.1", + "gzip-size": "^5.0.0", + "lodash": "^4.17.10", + "mkdirp": "^0.5.1", + "opener": "^1.5.1", + "ws": "^6.0.0" + }, + "bin": { + "webpack-bundle-analyzer": "lib/bin/analyzer.js" }, "engines": { - "node": ">=4" + "node": ">= 6.14.4" } }, - "node_modules/url/node_modules/punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - }, - "node_modules/use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha1-1QyMrHmhn7wg8pEfVuuXP04QBw8=", + "node_modules/webpack-bundle-analyzer/node_modules/acorn": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz", + "integrity": "sha1-PthCLW3sCeYSHMeoQ8qGozCoa1E=", "dev": true, + "bin": { + "acorn": "bin/acorn" + }, "engines": { - "node": ">=0.10.0" + "node": ">=0.4.0" } }, - "node_modules/utf8-byte-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", - "integrity": "sha1-9F8VDExm7uloGGUFq5P8u4rWv2E=", - "dev": true - }, - "node_modules/util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha1-MjZzNyDsZLsn9uJvQhqqLhtYjWE=", + "node_modules/webpack-chain": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-4.12.1.tgz", + "integrity": "sha1-bIQ5u7KrVQlS1g4eqTGRQZBsAqY=", "dev": true, "dependencies": { - "inherits": "2.0.3" + "deepmerge": "^1.5.2", + "javascript-stringify": "^1.6.0" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "node_modules/util.promisify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", - "integrity": "sha1-RA9xZaRZyaFtwUXrjnLzVocJcDA=", + "node_modules/webpack-dev-middleware": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.0.tgz", + "integrity": "sha1-73UdJfTppcijXaYAxf2jWCtcbP8=", "dev": true, "dependencies": { - "define-properties": "^1.1.2", - "object.getownpropertydescriptors": "^2.0.3" + "memory-fs": "^0.4.1", + "mime": "^2.4.2", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "webpack": "^4.0.0" } }, - "node_modules/util/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "node_modules/utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", - "dev": true - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "node_modules/webpack-dev-server": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.7.2.tgz", + "integrity": "sha1-95yqWXS3+LYyaO9UISIqhIbXkvU=", "dev": true, + "dependencies": { + "ansi-html": "0.0.7", + "bonjour": "^3.5.0", + "chokidar": "^2.1.6", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "debug": "^4.1.1", + "del": "^4.1.1", + "express": "^4.17.1", + "html-entities": "^1.2.1", + "http-proxy-middleware": "^0.19.1", + "import-local": "^2.0.0", + "internal-ip": "^4.3.0", + "ip": "^1.1.5", + "killable": "^1.0.1", + "loglevel": "^1.6.3", + "opn": "^5.5.0", + "p-retry": "^3.0.1", + "portfinder": "^1.0.20", + "schema-utils": "^1.0.0", + "selfsigned": "^1.10.4", + "semver": "^6.1.1", + "serve-index": "^1.9.1", + "sockjs": "0.3.19", + "sockjs-client": "1.3.0", + "spdy": "^4.0.0", + "strip-ansi": "^3.0.1", + "supports-color": "^6.1.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^3.7.0", + "webpack-log": "^2.0.0", + "yargs": "12.0.5" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, "engines": { - "node": ">= 0.4.0" + "node": ">= 6.11.5" + }, + "peerDependencies": { + "webpack": "^4.0.0" } }, - "node_modules/uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha1-G0r0lV6zB3xQHCOHL8ZROBFYcTE=", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "node_modules/webpack-dev-server/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true, - "bin": { - "uuid": "bin/uuid" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha1-/JH2uce6FchX9MssXe/uw51PQQo=", + "node_modules/webpack-dev-server/node_modules/cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha1-NIQi2+gtgAswIu709qwQvy5NG0k=", "dev": true, "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" } }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "node_modules/webpack-dev-server/node_modules/cliui/node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true, "engines": { - "node": ">= 0.8" + "node": ">=4" } }, - "node_modules/vendors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.3.tgz", - "integrity": "sha1-pkZ3gavTZiF8BQ+CAuflDMnu+MA=", - "dev": true - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "node_modules/webpack-dev-server/node_modules/cliui/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, - "engines": [ - "node >=0.6.0" - ], "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/vm-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", - "integrity": "sha1-vXbWojMj4sqP+hICjcBFWcdfkBk=", - "dev": true - }, - "node_modules/vue": { - "version": "2.6.10", - "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.10.tgz", - "integrity": "sha1-pysaQqTYKnIepDjRtr9V5mGVxjc=" - }, - "node_modules/vue-cli-plugin-electron-builder": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/vue-cli-plugin-electron-builder/-/vue-cli-plugin-electron-builder-1.3.6.tgz", - "integrity": "sha1-mxhXtr4XX3Bo29H5BXU8ENfaRgc=", + "node_modules/webpack-dev-server/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=", "dev": true, "dependencies": { - "chokidar": "^2.1.5", - "electron-builder": "^20.29.0", - "execa": "^1.0.0", - "friendly-errors-webpack-plugin": "^1.7.0", - "fs-extra": "^7.0.0", - "lodash.merge": "^4.6.1", - "portfinder": "^1.0.16", - "pumpify": "^1.5.1", - "semver": "^6.0.0", - "shebang-loader": "^0.0.1", - "spectron": "^7.0.0", - "split2": "^3.0.0", - "terser-webpack-plugin": "^1.1.0", - "through2-filter": "^3.0.0", - "through2-map": "^3.0.0", - "unzip-crx": "^0.2.0", - "webpack": "^4.18.0", - "webpack-chain": "^5.0.0", - "yargs": "^13.2.2" + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/vue-cli-plugin-electron-builder/node_modules/javascript-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.0.0.tgz", - "integrity": "sha1-73UCFq5mUE/9ZwtoyLiqB733tYg=", + "node_modules/webpack-dev-server/node_modules/get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha1-+Xj6TJDR3+f/LWvtoqUV5xO9z0o=", "dev": true }, - "node_modules/vue-cli-plugin-electron-builder/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=", + "node_modules/webpack-dev-server/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, - "bin": { - "semver": "bin/semver.js" + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/vue-cli-plugin-electron-builder/node_modules/webpack-chain": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-5.2.4.tgz", - "integrity": "sha1-zDZlopam7c2nODJFmRA6xuIV3aM=", + "node_modules/webpack-dev-server/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4=", "dev": true, "dependencies": { - "deepmerge": "^1.5.2", - "javascript-stringify": "^2.0.0" + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/vue-eslint-parser": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-2.0.3.tgz", - "integrity": "sha1-wmjJbG2Uz+PZOKX3WTlZsMozYNE=", + "node_modules/webpack-dev-server/node_modules/p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha1-QXyZQeYCepq8ulCS3SkE4lW1+8I=", "dev": true, - "optional": true, "dependencies": { - "debug": "^3.1.0", - "eslint-scope": "^3.7.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^3.5.2", - "esquery": "^1.0.0", - "lodash": "^4.17.4" + "p-try": "^2.0.0" }, "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": ">=3.9.0" + "node": ">=6" } }, - "node_modules/vue-eslint-parser/node_modules/debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "node_modules/webpack-dev-server/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=", "dev": true, - "optional": true, "dependencies": { - "ms": "^2.1.1" + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/vue-eslint-parser/node_modules/eslint-scope": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", - "integrity": "sha1-u1ByANPRf2AkdjYWC0gmKEsQhTU=", + "node_modules/webpack-dev-server/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha1-yyhoVA4xPWHeWPr741zpAE1VQOY=", "dev": true, - "optional": true, - "dependencies": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - }, "engines": { - "node": ">=4.0.0" + "node": ">=6" } }, - "node_modules/vue-hot-reload-api": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.3.tgz", - "integrity": "sha1-J1b0bLMlgFTF9HI96K5+hzAqHM8=", + "node_modules/webpack-dev-server/node_modules/require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", "dev": true }, - "node_modules/vue-loader": { - "version": "15.7.1", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.7.1.tgz", - "integrity": "sha1-bMrNQSKqgPabqqwI/ylaYuOu/P0=", + "node_modules/webpack-dev-server/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", "dev": true, "dependencies": { - "@vue/component-compiler-utils": "^3.0.0", - "hash-sum": "^1.0.2", - "loader-utils": "^1.1.0", - "vue-hot-reload-api": "^2.3.0", - "vue-style-loader": "^4.1.0" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" }, - "peerDependencies": { - "css-loader": "*", - "webpack": "^4.1.0 || ^5.0.0-0" + "engines": { + "node": ">= 4" } }, - "node_modules/vue-loader/node_modules/@vue/component-compiler-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.0.0.tgz", - "integrity": "sha1-0W+ia4NsBt9bqutF89gK/EfjVjQ=", + "node_modules/webpack-dev-server/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=", "dev": true, - "dependencies": { - "consolidate": "^0.15.1", - "hash-sum": "^1.0.2", - "lru-cache": "^4.1.2", - "merge-source-map": "^1.1.0", - "postcss": "^7.0.14", - "postcss-selector-parser": "^5.0.0", - "prettier": "1.16.3", - "source-map": "~0.6.1", - "vue-template-es2015-compiler": "^1.9.0" + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/vue-loader/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=", + "node_modules/webpack-dev-server/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/vue-loader/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "node_modules/webpack-dev-server/node_modules/supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha1-B2Srxpxj1ayELdSGfo0CXogN+PM=", "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/vue-loader/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "node_modules/vue-router": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.0.7.tgz", - "integrity": "sha1-s2yhB7SsuP9bxP+CRYQFnCP8uHs=" - }, - "node_modules/vue-style-loader": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz", - "integrity": "sha1-3t80mAbyXOtOZPOtfApE+6c1/Pg=", + "node_modules/webpack-dev-server/node_modules/wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, "dependencies": { - "hash-sum": "^1.0.2", - "loader-utils": "^1.0.2" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/vue-template-compiler": { - "version": "2.6.10", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.10.tgz", - "integrity": "sha1-MjtPNJXwT6o1AzN6gvXWUHeZycw=", + "node_modules/webpack-dev-server/node_modules/wrap-ansi/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "dependencies": { - "de-indent": "^1.0.2", - "he": "^1.1.0" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/vue-template-es2015-compiler": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz", - "integrity": "sha1-HuO8mhbsv1EYvjNLsV+cRvgvWCU=", - "dev": true - }, - "node_modules/watchpack": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", - "integrity": "sha1-S8EsLr6KonenHx0/FNaFx7RGzQA=", - "dev": true, - "dependencies": { - "chokidar": "^2.0.2", - "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0" - } - }, - "node_modules/wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha1-wdjRSTFtPqhShIiVy2oL/oh7h98=", + "node_modules/webpack-dev-server/node_modules/yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha1-BfWZe2CWR7ZPZrgeO0sQo2jnrRM=", "dev": true, "dependencies": { - "minimalistic-assert": "^1.0.0" + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" } }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "node_modules/webpack-dev-server/node_modules/yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha1-h5oIZZc7yp9rq1y987HGfsfTvPQ=", "dev": true, "dependencies": { - "defaults": "^1.0.3" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } }, - "node_modules/wdio-dot-reporter": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/wdio-dot-reporter/-/wdio-dot-reporter-0.0.10.tgz", - "integrity": "sha1-+s+3ycWYQUmVH1nLw80HUhAc8OA=", - "dev": true - }, - "node_modules/webdriverio": { - "version": "4.14.4", - "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-4.14.4.tgz", - "integrity": "sha1-96lOmmUwgZeWCI9CsAmDPYPeA4Y=", - "deprecated": "outdated version, please use @next", + "node_modules/webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha1-W3ko4GN1k/EZ0y9iJ8HgrDHhtH8=", "dev": true, "dependencies": { - "archiver": "~2.1.0", - "babel-runtime": "^6.26.0", - "css-parse": "^2.0.0", - "css-value": "~0.0.1", - "deepmerge": "~2.0.1", - "ejs": "~2.5.6", - "gaze": "~1.1.2", - "glob": "~7.1.1", - "grapheme-splitter": "^1.0.2", - "inquirer": "~3.3.0", - "json-stringify-safe": "~5.0.1", - "mkdirp": "~0.5.1", - "npm-install-package": "~2.1.0", - "optimist": "~0.6.1", - "q": "~1.5.0", - "request": "^2.83.0", - "rgb2hex": "^0.1.9", - "safe-buffer": "~5.1.1", - "supports-color": "~5.0.0", - "url": "~0.11.0", - "wdio-dot-reporter": "~0.0.8", - "wgxpath": "~1.0.0" - }, - "bin": { - "wdio": "bin/wdio" + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" }, "engines": { - "node": ">= 4.8.5" + "node": ">= 6" } }, - "node_modules/webdriverio/node_modules/deepmerge": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.0.1.tgz", - "integrity": "sha1-JcHCTxEPuRT4AAG5JSZN138/QxI=", + "node_modules/webpack-merge": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.1.tgz", + "integrity": "sha1-XpI8+ALqKs5P1a8dMkc2imM0ibQ=", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "lodash": "^4.17.5" } }, - "node_modules/webdriverio/node_modules/ejs": { - "version": "2.5.9", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.9.tgz", - "integrity": "sha1-e6JUWCpWDSZ0NxCaaDVBEkdbDOU=", + "node_modules/webpack-sources": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", + "integrity": "sha1-KijcufH0X+lg2PFJMlK17mUw+oU=", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" } }, - "node_modules/webdriverio/node_modules/has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "node_modules/webpack-sources/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/webdriverio/node_modules/supports-color": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.0.1.tgz", - "integrity": "sha1-HFMx8iJQyEICgFsvF63xZpnzo5o=", + "node_modules/websocket-driver": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz", + "integrity": "sha1-otTg1PTxFvHmKX66WLBdQwEA6fk=", "dev": true, "dependencies": { - "has-flag": "^2.0.0" + "http-parser-js": ">=0.4.0 <0.4.11", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" }, "engines": { - "node": ">=4" + "node": ">=0.8.0" } }, - "node_modules/webpack": { - "version": "4.28.4", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.28.4.tgz", - "integrity": "sha1-HdrmyJiH1++3Uq3ww80yubB+rNA=", + "node_modules/websocket-extensions": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", + "integrity": "sha1-XS/yKXcAPsaHpLhwc9+7rBRszyk=", "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-module-context": "1.7.11", - "@webassemblyjs/wasm-edit": "1.7.11", - "@webassemblyjs/wasm-parser": "1.7.11", - "acorn": "^5.6.2", - "acorn-dynamic-import": "^3.0.0", - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0", - "chrome-trace-event": "^1.0.0", - "enhanced-resolve": "^4.1.0", - "eslint-scope": "^4.0.0", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.3.0", - "loader-utils": "^1.1.0", - "memory-fs": "~0.4.1", - "micromatch": "^3.1.8", - "mkdirp": "~0.5.0", - "neo-async": "^2.5.0", - "node-libs-browser": "^2.0.0", - "schema-utils": "^0.4.4", - "tapable": "^1.1.0", - "terser-webpack-plugin": "^1.1.0", - "watchpack": "^1.5.0", - "webpack-sources": "^1.3.0" - }, - "bin": { - "webpack": "bin/webpack.js" - }, "engines": { - "node": ">=6.11.5" + "node": ">=0.8.0" } }, - "node_modules/webpack-bundle-analyzer": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.3.2.tgz", - "integrity": "sha1-PaczqQD1FZFOcp/OvNTEDd5x/G8=", + "node_modules/wgxpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wgxpath/-/wgxpath-1.0.0.tgz", + "integrity": "sha1-7vikudVYzEla06mit1FZfs2a9pA=", + "dev": true + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=", "dev": true, "dependencies": { - "acorn": "^6.0.7", - "acorn-walk": "^6.1.1", - "bfj": "^6.1.1", - "chalk": "^2.4.1", - "commander": "^2.18.0", - "ejs": "^2.6.1", - "express": "^4.16.3", - "filesize": "^3.6.1", - "gzip-size": "^5.0.0", - "lodash": "^4.17.10", - "mkdirp": "^0.5.1", - "opener": "^1.5.1", - "ws": "^6.0.0" + "isexe": "^2.0.0" }, "bin": { - "webpack-bundle-analyzer": "lib/bin/analyzer.js" - }, - "engines": { - "node": ">= 6.14.4" + "which": "bin/which" } }, - "node_modules/webpack-bundle-analyzer/node_modules/acorn": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz", - "integrity": "sha1-PthCLW3sCeYSHMeoQ8qGozCoa1E=", + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "node_modules/widest-line": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "integrity": "sha1-dDh2RzDsfvQ4HOTfgvuYpTFCo/w=", "dev": true, - "bin": { - "acorn": "bin/acorn" + "dependencies": { + "string-width": "^2.1.1" }, "engines": { - "node": ">=0.4.0" + "node": ">=4" } }, - "node_modules/webpack-chain": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-4.12.1.tgz", - "integrity": "sha1-bIQ5u7KrVQlS1g4eqTGRQZBsAqY=", + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "node_modules/worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha1-JqlMU5G7ypJhUgAvabhKS/dy5ag=", "dev": true, "dependencies": { - "deepmerge": "^1.5.2", - "javascript-stringify": "^1.6.0" + "errno": "~0.1.7" } }, - "node_modules/webpack-dev-middleware": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.0.tgz", - "integrity": "sha1-73UdJfTppcijXaYAxf2jWCtcbP8=", + "node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha1-H9H2cjXVttD+54EFYAG/tpTAOwk=", "dev": true, "dependencies": { - "memory-fs": "^0.4.1", - "mime": "^2.4.2", - "range-parser": "^1.2.1", - "webpack-log": "^2.0.0" + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" }, "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "webpack": "^4.0.0" + "node": ">=6" } }, - "node_modules/webpack-dev-server": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.7.2.tgz", - "integrity": "sha1-95yqWXS3+LYyaO9UISIqhIbXkvU=", + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha1-InZ74htirxCBV0MG9prFG2IgOWE=", "dev": true, "dependencies": { - "ansi-html": "0.0.7", - "bonjour": "^3.5.0", - "chokidar": "^2.1.6", - "compression": "^1.7.4", - "connect-history-api-fallback": "^1.6.0", - "debug": "^4.1.1", - "del": "^4.1.1", - "express": "^4.17.1", - "html-entities": "^1.2.1", - "http-proxy-middleware": "^0.19.1", - "import-local": "^2.0.0", - "internal-ip": "^4.3.0", - "ip": "^1.1.5", - "killable": "^1.0.1", - "loglevel": "^1.6.3", - "opn": "^5.5.0", - "p-retry": "^3.0.1", - "portfinder": "^1.0.20", - "schema-utils": "^1.0.0", - "selfsigned": "^1.10.4", - "semver": "^6.1.1", - "serve-index": "^1.9.1", - "sockjs": "0.3.19", - "sockjs-client": "1.3.0", - "spdy": "^4.0.0", - "strip-ansi": "^3.0.1", - "supports-color": "^6.1.0", - "url": "^0.11.0", - "webpack-dev-middleware": "^3.7.0", - "webpack-log": "^2.0.0", - "yargs": "12.0.5" - }, - "bin": { - "webpack-dev-server": "bin/webpack-dev-server.js" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" }, "engines": { - "node": ">= 6.11.5" - }, - "peerDependencies": { - "webpack": "^4.0.0" + "node": ">=6" } }, - "node_modules/webpack-dev-server/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", "dev": true, + "optional": true, + "dependencies": { + "mkdirp": "^0.5.1" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/webpack-dev-server/node_modules/cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha1-NIQi2+gtgAswIu709qwQvy5NG0k=", + "node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha1-H9Lprh3z51uNjDZ0Q8aS1MqB9IE=", "dev": true, "dependencies": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" } }, - "node_modules/webpack-dev-server/node_modules/cliui/node_modules/ansi-regex": { + "node_modules/ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha1-RC/fCkftZPWbal2P8TD0dI7VJPs=", + "dev": true, + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/xdg-basedir": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", "dev": true, "engines": { "node": ">=4" } }, - "node_modules/webpack-dev-server/node_modules/cliui/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "node_modules/xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, "engines": { - "node": ">=4" + "node": ">=4.0" } }, - "node_modules/webpack-dev-server/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=", + "node_modules/xmldom": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", + "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=", + "deprecated": "Deprecated due to CVE-2021-21366 resolved in 0.5.0", + "engines": { + "node": ">=0.1" + } + }, + "node_modules/xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha1-u3J3n1+kZRhrH0OPZ0+jR/2121Q=", "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, "engines": { - "node": ">=6" + "node": ">=0.4" } }, - "node_modules/webpack-dev-server/node_modules/get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha1-+Xj6TJDR3+f/LWvtoqUV5xO9z0o=", + "node_modules/y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha1-le+U+F7MgdAHwmThkKEg8KPIVms=", "dev": true }, - "node_modules/webpack-dev-server/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "node_modules/yaku": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/yaku/-/yaku-0.16.7.tgz", + "integrity": "sha1-HRlceKqbW/hHnIlblQT9TwhHmE4=", + "dev": true + }, + "node_modules/yallist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha1-tLBJ4xS+VF486AIjbWzSLNkcPek=", + "dev": true + }, + "node_modules/yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha1-TGV6VeB+Xyz5R/ijZlZ8BKDe3IM=", "dev": true, "dependencies": { - "number-is-nan": "^1.0.0" + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + }, + "node_modules/yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha1-0mBYUyqgbTZf4JH2ofwGsvfl7KA=", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/yargs/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/webpack-dev-server/node_modules/locate-path": { + "node_modules/yargs/node_modules/locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4=", @@ -16819,7 +16620,7 @@ "node": ">=6" } }, - "node_modules/webpack-dev-server/node_modules/p-limit": { + "node_modules/yargs/node_modules/p-limit": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", "integrity": "sha1-QXyZQeYCepq8ulCS3SkE4lW1+8I=", @@ -16831,7 +16632,7 @@ "node": ">=6" } }, - "node_modules/webpack-dev-server/node_modules/p-locate": { + "node_modules/yargs/node_modules/p-locate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=", @@ -16843,7 +16644,7 @@ "node": ">=6" } }, - "node_modules/webpack-dev-server/node_modules/p-try": { + "node_modules/yargs/node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha1-yyhoVA4xPWHeWPr741zpAE1VQOY=", @@ -16852,3088 +16653,3639 @@ "node": ">=6" } }, - "node_modules/webpack-dev-server/node_modules/require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "node_modules/webpack-dev-server/node_modules/schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", + "node_modules/yargs/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha1-InZ74htirxCBV0MG9prFG2IgOWE=", "dev": true, "dependencies": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" }, "engines": { - "node": ">= 4" + "node": ">=6" } }, - "node_modules/webpack-dev-server/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=", + "node_modules/yauzl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", + "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", "dev": true, - "bin": { - "semver": "bin/semver.js" + "dependencies": { + "fd-slicer": "~1.0.1" } }, - "node_modules/webpack-dev-server/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "node_modules/yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" + }, + "node_modules/yorkie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yorkie/-/yorkie-2.0.0.tgz", + "integrity": "sha1-kkEZEtQ1IU4SxRwq4Qk+VLa7g9k=", "dev": true, + "hasInstallScript": true, "dependencies": { - "ansi-regex": "^2.0.0" + "execa": "^0.8.0", + "is-ci": "^1.0.10", + "normalize-path": "^1.0.0", + "strip-indent": "^2.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/webpack-dev-server/node_modules/supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha1-B2Srxpxj1ayELdSGfo0CXogN+PM=", + "node_modules/yorkie/node_modules/cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=6" + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" } }, - "node_modules/webpack-dev-server/node_modules/wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "node_modules/yorkie/node_modules/execa": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", + "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=", "dev": true, "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/webpack-dev-server/node_modules/wrap-ansi/node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "node_modules/yorkie/node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/webpack-dev-server/node_modules/yargs": { - "version": "12.0.5", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", - "integrity": "sha1-BfWZe2CWR7ZPZrgeO0sQo2jnrRM=", + "node_modules/yorkie/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=", "dev": true, "dependencies": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" } }, - "node_modules/webpack-dev-server/node_modules/yargs-parser": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", - "integrity": "sha1-h5oIZZc7yp9rq1y987HGfsfTvPQ=", + "node_modules/yorkie/node_modules/normalize-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-1.0.0.tgz", + "integrity": "sha1-MtDkcvkf80VwHBWoMRAY07CpA3k=", "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/webpack-log": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", - "integrity": "sha1-W3ko4GN1k/EZ0y9iJ8HgrDHhtH8=", + "node_modules/yorkie/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "node_modules/zip-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz", + "integrity": "sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ=", "dev": true, "dependencies": { - "ansi-colors": "^3.0.0", - "uuid": "^3.3.2" + "archiver-utils": "^1.3.0", + "compress-commons": "^1.2.0", + "lodash": "^4.8.0", + "readable-stream": "^2.0.0" }, "engines": { - "node": ">= 6" + "node": ">= 0.10.0" + } + } + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha1-vAeC9tafe31JUxIZaZuYj2aaj50=", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" } }, - "node_modules/webpack-merge": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.1.tgz", - "integrity": "sha1-XpI8+ALqKs5P1a8dMkc2imM0ibQ=", + "@babel/core": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.5.5.tgz", + "integrity": "sha1-F7JobvDWvFj5Y93daKtml1VYLDA=", "dev": true, - "dependencies": { - "lodash": "^4.17.5" + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.5.5", + "@babel/helpers": "^7.5.5", + "@babel/parser": "^7.5.5", + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5", + "convert-source-map": "^1.1.0", + "debug": "^4.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" } }, - "node_modules/webpack-sources": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", - "integrity": "sha1-KijcufH0X+lg2PFJMlK17mUw+oU=", + "@babel/generator": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz", + "integrity": "sha1-hzp/k2o8iUkbQ1NtEiRbYmZk488=", "dev": true, - "dependencies": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" + "requires": { + "@babel/types": "^7.5.5", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" } }, - "node_modules/webpack-sources/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "@babel/helper-annotate-as-pure": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", + "integrity": "sha1-Mj053QtQ4Qx8Bsp9djjmhk2MXDI=", "dev": true, - "engines": { - "node": ">=0.10.0" + "requires": { + "@babel/types": "^7.0.0" } }, - "node_modules/websocket-driver": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz", - "integrity": "sha1-otTg1PTxFvHmKX66WLBdQwEA6fk=", + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", + "integrity": "sha1-a2lijf5Ah3mODE7Zjj1Kay+9L18=", "dev": true, - "dependencies": { - "http-parser-js": ">=0.4.0 <0.4.11", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - }, - "engines": { - "node": ">=0.8.0" + "requires": { + "@babel/helper-explode-assignable-expression": "^7.1.0", + "@babel/types": "^7.0.0" } }, - "node_modules/websocket-extensions": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha1-XS/yKXcAPsaHpLhwc9+7rBRszyk=", + "@babel/helper-call-delegate": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz", + "integrity": "sha1-h8H4yhmtVSpzanonscH8+LH/H0M=", "dev": true, - "engines": { - "node": ">=0.8.0" + "requires": { + "@babel/helper-hoist-variables": "^7.4.4", + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4" } }, - "node_modules/wgxpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wgxpath/-/wgxpath-1.0.0.tgz", - "integrity": "sha1-7vikudVYzEla06mit1FZfs2a9pA=", - "dev": true + "@babel/helper-create-class-features-plugin": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.5.5.tgz", + "integrity": "sha1-QB8wLI3bwO3Tb3xrKIfY+hEi5aQ=", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-member-expression-to-functions": "^7.5.5", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.5.5", + "@babel/helper-split-export-declaration": "^7.4.4" + } }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=", + "@babel/helper-define-map": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz", + "integrity": "sha1-PewywgRvN+CbKMk+sLED/Sol02k=", "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/types": "^7.5.5", + "lodash": "^4.17.13" } }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true + "@babel/helper-explode-assignable-expression": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", + "integrity": "sha1-U3+hP28WdN90WwwA7I/k6ZaByPY=", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } }, - "node_modules/widest-line": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", - "integrity": "sha1-dDh2RzDsfvQ4HOTfgvuYpTFCo/w=", + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha1-oM6wFoX3M1XUNgwSR/WCv6/I/1M=", "dev": true, - "dependencies": { - "string-width": "^2.1.1" - }, - "engines": { - "node": ">=4" + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" } }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha1-g1ctQyDipGVyY3NBE8QoaLZOScM=", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } }, - "node_modules/worker-farm": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", - "integrity": "sha1-JqlMU5G7ypJhUgAvabhKS/dy5ag=", + "@babel/helper-hoist-variables": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz", + "integrity": "sha1-Api18lyMCcUxAtUqxKmPdz6yhQo=", "dev": true, - "dependencies": { - "errno": "~0.1.7" + "requires": { + "@babel/types": "^7.4.4" } }, - "node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha1-H9H2cjXVttD+54EFYAG/tpTAOwk=", + "@babel/helper-member-expression-to-functions": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz", + "integrity": "sha1-H7W47ERTqTxDnun+Ou6kqEt2tZA=", "dev": true, - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "engines": { - "node": ">=6" + "requires": { + "@babel/types": "^7.5.5" } }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha1-InZ74htirxCBV0MG9prFG2IgOWE=", + "@babel/helper-module-imports": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", + "integrity": "sha1-lggbcRHkhtpNLNlxrRpP4hbMLj0=", "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" + "requires": { + "@babel/types": "^7.0.0" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "@babel/helper-module-transforms": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz", + "integrity": "sha1-+E/4oJA43Lyh/UNVZhpQCTcWW0o=", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/template": "^7.4.4", + "@babel/types": "^7.5.5", + "lodash": "^4.17.13" + } }, - "node_modules/write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "@babel/helper-optimise-call-expression": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", + "integrity": "sha1-opIMVwKwc8Fd5REGIAqoytIEl9U=", "dev": true, - "optional": true, - "dependencies": { - "mkdirp": "^0.5.1" - }, - "engines": { - "node": ">=0.10.0" + "requires": { + "@babel/types": "^7.0.0" } }, - "node_modules/write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha1-H9Lprh3z51uNjDZ0Q8aS1MqB9IE=", + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha1-u7P77phmHFaQNCN8wDlnupm08lA=", + "dev": true + }, + "@babel/helper-regex": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.5.5.tgz", + "integrity": "sha1-CqaCT3EAouDonBUnwjk2wVLKs1E=", "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" + "requires": { + "lodash": "^4.17.13" } }, - "node_modules/ws": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", - "integrity": "sha1-RC/fCkftZPWbal2P8TD0dI7VJPs=", + "@babel/helper-remap-async-to-generator": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", + "integrity": "sha1-Nh2AghtvONp1vT8HheziCojF/n8=", "dev": true, - "dependencies": { - "async-limiter": "~1.0.0" + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-wrap-function": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" } }, - "node_modules/xdg-basedir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", - "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", + "@babel/helper-replace-supers": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz", + "integrity": "sha1-+EzkPfAxIi0rrQaNJibLV5nDS8I=", "dev": true, - "engines": { - "node": ">=4" + "requires": { + "@babel/helper-member-expression-to-functions": "^7.5.5", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5" } }, - "node_modules/xmlbuilder": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", + "@babel/helper-simple-access": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", + "integrity": "sha1-Ze65VMjCRb6qToWdphiPOdceWFw=", "dev": true, - "engines": { - "node": ">=4.0" + "requires": { + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" } }, - "node_modules/xmldom": { - "version": "0.1.27", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", - "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=", - "deprecated": "Deprecated due to CVE-2021-21366 resolved in 0.5.0", - "engines": { - "node": ">=0.1" + "@babel/helper-split-export-declaration": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha1-/5SJSjQL549T8GrwOLIFxJ2ZNnc=", + "dev": true, + "requires": { + "@babel/types": "^7.4.4" } }, - "node_modules/xmlhttprequest-ssl": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", - "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", - "engines": { - "node": ">=0.4.0" + "@babel/helper-wrap-function": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz", + "integrity": "sha1-xOABJEV2nigVtVKW6tQ6lYVJ9vo=", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.2.0" } }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha1-u3J3n1+kZRhrH0OPZ0+jR/2121Q=", + "@babel/helpers": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.5.5.tgz", + "integrity": "sha1-Y5CNKnOUIinR5mhbwqDnMN3jt14=", "dev": true, - "engines": { - "node": ">=0.4" + "requires": { + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5" } }, - "node_modules/y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha1-le+U+F7MgdAHwmThkKEg8KPIVms=", - "dev": true + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha1-VtETEr2SSPphlZHQJHK+boyzJUA=", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } }, - "node_modules/yaku": { - "version": "0.16.7", - "resolved": "https://registry.npmjs.org/yaku/-/yaku-0.16.7.tgz", - "integrity": "sha1-HRlceKqbW/hHnIlblQT9TwhHmE4=", + "@babel/parser": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", + "integrity": "sha1-AvB3rIgX099Kgy71neZ1Zeccyks=", "dev": true }, - "node_modules/yallist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha1-tLBJ4xS+VF486AIjbWzSLNkcPek=", - "dev": true - }, - "node_modules/yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha1-TGV6VeB+Xyz5R/ijZlZ8BKDe3IM=", + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz", + "integrity": "sha1-somzBmadzkrSCwJSiJoVdoydQX4=", "dev": true, - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0", + "@babel/plugin-syntax-async-generators": "^7.2.0" } }, - "node_modules/yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha1-0mBYUyqgbTZf4JH2ofwGsvfl7KA=", + "@babel/plugin-proposal-class-properties": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.5.5.tgz", + "integrity": "sha1-qXTPrh43wxEOcfPGouSLjnGVjNQ=", "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "requires": { + "@babel/helper-create-class-features-plugin": "^7.5.5", + "@babel/helper-plugin-utils": "^7.0.0" } }, - "node_modules/yargs/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=", + "@babel/plugin-proposal-decorators": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.4.4.tgz", + "integrity": "sha1-3psqGoqwGW83jiqC8QtuKjbyHMA=", "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" + "requires": { + "@babel/helper-create-class-features-plugin": "^7.4.4", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-decorators": "^7.2.0" } }, - "node_modules/yargs/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4=", + "@babel/plugin-proposal-json-strings": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", + "integrity": "sha1-Vo7MRGxhSK5rJn8CVREwiR4p8xc=", "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-json-strings": "^7.2.0" } }, - "node_modules/yargs/node_modules/p-limit": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", - "integrity": "sha1-QXyZQeYCepq8ulCS3SkE4lW1+8I=", + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz", + "integrity": "sha1-YZOXRPcbp2o65Gte6hilTBbSLlg=", "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0" } }, - "node_modules/yargs/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=", + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz", + "integrity": "sha1-E12B7baKCB5V5W7EhUHs6AZcOPU=", "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.2.0" } }, - "node_modules/yargs/node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha1-yyhoVA4xPWHeWPr741zpAE1VQOY=", + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz", + "integrity": "sha1-UB/9mCbAuR2iJpByByKsfLHKnHg=", "dev": true, - "engines": { - "node": ">=6" + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.4.4", + "regexpu-core": "^4.5.4" } }, - "node_modules/yargs/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha1-InZ74htirxCBV0MG9prFG2IgOWE=", + "@babel/plugin-syntax-async-generators": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz", + "integrity": "sha1-aeHw2zTG9aDPfiszI78VmnbIy38=", "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" } }, - "node_modules/yauzl": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", - "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", + "@babel/plugin-syntax-decorators": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.2.0.tgz", + "integrity": "sha1-xQsblX3MaeSxEntl4cM+72FXDBs=", "dev": true, - "dependencies": { - "fd-slicer": "~1.0.1" + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" } }, - "node_modules/yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" + "@babel/plugin-syntax-dynamic-import": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz", + "integrity": "sha1-acFZ/69JmBIhYa2OvF5tH1XfhhI=", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } }, - "node_modules/yorkie": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yorkie/-/yorkie-2.0.0.tgz", - "integrity": "sha1-kkEZEtQ1IU4SxRwq4Qk+VLa7g9k=", + "@babel/plugin-syntax-json-strings": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", + "integrity": "sha1-cr0T9v/h0lk4Ep0qGGsR/WKVFHA=", "dev": true, - "hasInstallScript": true, - "dependencies": { - "execa": "^0.8.0", - "is-ci": "^1.0.10", - "normalize-path": "^1.0.0", - "strip-indent": "^2.0.0" - }, - "engines": { - "node": ">=4" + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" } }, - "node_modules/yorkie/node_modules/cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "@babel/plugin-syntax-jsx": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz", + "integrity": "sha1-C4WjtLx830zEuL8jYzW5B8oi58c=", "dev": true, - "dependencies": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" } }, - "node_modules/yorkie/node_modules/execa": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", - "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=", + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", + "integrity": "sha1-O3o+czUQxX6CC5FCpleayLDfrS4=", "dev": true, - "dependencies": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=4" + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" } }, - "node_modules/yorkie/node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz", + "integrity": "sha1-qUAT1u2okI3+akd+f57ahWVuz1w=", "dev": true, - "engines": { - "node": ">=4" + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" } }, - "node_modules/yorkie/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=", + "@babel/plugin-transform-arrow-functions": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", + "integrity": "sha1-mur75Nb/xlY7+Pg3IJFijwB3lVA=", "dev": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" } }, - "node_modules/yorkie/node_modules/normalize-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-1.0.0.tgz", - "integrity": "sha1-MtDkcvkf80VwHBWoMRAY07CpA3k=", + "@babel/plugin-transform-async-to-generator": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz", + "integrity": "sha1-iaOEigFmYjtbxIEWS1k2q5R+iH4=", "dev": true, - "engines": { - "node": ">=0.10.0" + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0" } }, - "node_modules/yorkie/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "node_modules/zip-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz", - "integrity": "sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ=", - "dev": true, - "dependencies": { - "archiver-utils": "^1.3.0", - "compress-commons": "^1.2.0", - "lodash": "^4.8.0", - "readable-stream": "^2.0.0" - }, - "engines": { - "node": ">= 0.10.0" - } - } - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", - "integrity": "sha1-vAeC9tafe31JUxIZaZuYj2aaj50=", + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz", + "integrity": "sha1-XTzBHo1d3XUqpkyRSNDbbLef0ZA=", "dev": true, "requires": { - "@babel/highlight": "^7.0.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, - "@babel/core": { + "@babel/plugin-transform-block-scoping": { "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.5.5.tgz", - "integrity": "sha1-F7JobvDWvFj5Y93daKtml1VYLDA=", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.5.5.tgz", + "integrity": "sha1-o185XlQCgi8Q0hGfb44EXjY5os4=", "dev": true, "requires": { - "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.5.5", - "@babel/helpers": "^7.5.5", - "@babel/parser": "^7.5.5", - "@babel/template": "^7.4.4", - "@babel/traverse": "^7.5.5", - "@babel/types": "^7.5.5", - "convert-source-map": "^1.1.0", - "debug": "^4.1.0", - "json5": "^2.1.0", - "lodash": "^4.17.13", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" + "@babel/helper-plugin-utils": "^7.0.0", + "lodash": "^4.17.13" } }, - "@babel/generator": { + "@babel/plugin-transform-classes": { "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz", - "integrity": "sha1-hzp/k2o8iUkbQ1NtEiRbYmZk488=", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz", + "integrity": "sha1-0JQpnZvWgKFKKg7a44MFrWD7Tek=", "dev": true, "requires": { - "@babel/types": "^7.5.5", - "jsesc": "^2.5.1", - "lodash": "^4.17.13", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-define-map": "^7.5.5", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.5.5", + "@babel/helper-split-export-declaration": "^7.4.4", + "globals": "^11.1.0" } }, - "@babel/helper-annotate-as-pure": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", - "integrity": "sha1-Mj053QtQ4Qx8Bsp9djjmhk2MXDI=", + "@babel/plugin-transform-computed-properties": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz", + "integrity": "sha1-g6ffamWIZbHI9kHVEMbzryICFto=", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", - "integrity": "sha1-a2lijf5Ah3mODE7Zjj1Kay+9L18=", + "@babel/plugin-transform-destructuring": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.5.0.tgz", + "integrity": "sha1-9sCf3+P5RRb/B0/od9t7ye8FhVo=", "dev": true, "requires": { - "@babel/helper-explode-assignable-expression": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, - "@babel/helper-call-delegate": { + "@babel/plugin-transform-dotall-regex": { "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz", - "integrity": "sha1-h8H4yhmtVSpzanonscH8+LH/H0M=", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz", + "integrity": "sha1-NhoUi8lRREMSxpRG127R6o5EUMM=", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.4.4", - "@babel/traverse": "^7.4.4", - "@babel/types": "^7.4.4" + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.4.4", + "regexpu-core": "^4.5.4" } }, - "@babel/helper-create-class-features-plugin": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.5.5.tgz", - "integrity": "sha1-QB8wLI3bwO3Tb3xrKIfY+hEi5aQ=", + "@babel/plugin-transform-duplicate-keys": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz", + "integrity": "sha1-xdv1EGv4TN9pEiLAl0wSsd+TGFM=", "dev": true, "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-member-expression-to-functions": "^7.5.5", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.5.5", - "@babel/helper-split-export-declaration": "^7.4.4" + "@babel/helper-plugin-utils": "^7.0.0" } }, - "@babel/helper-define-map": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz", - "integrity": "sha1-PewywgRvN+CbKMk+sLED/Sol02k=", + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz", + "integrity": "sha1-pjhoKJ5bQAf3BU1GSRr1FDV2YAg=", "dev": true, "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/types": "^7.5.5", - "lodash": "^4.17.13" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" } }, - "@babel/helper-explode-assignable-expression": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", - "integrity": "sha1-U3+hP28WdN90WwwA7I/k6ZaByPY=", + "@babel/plugin-transform-for-of": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz", + "integrity": "sha1-Amf8c14kyAi6FzhmxsTRRA/DxVY=", "dev": true, "requires": { - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, - "@babel/helper-function-name": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", - "integrity": "sha1-oM6wFoX3M1XUNgwSR/WCv6/I/1M=", + "@babel/plugin-transform-function-name": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz", + "integrity": "sha1-4UNhFquwYQwiWQlISHVKxSMJIq0=", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" } }, - "@babel/helper-get-function-arity": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", - "integrity": "sha1-g1ctQyDipGVyY3NBE8QoaLZOScM=", + "@babel/plugin-transform-literals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz", + "integrity": "sha1-aQNT6B+SZ9rU/Yz9d+r6hqulPqE=", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, - "@babel/helper-hoist-variables": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz", - "integrity": "sha1-Api18lyMCcUxAtUqxKmPdz6yhQo=", + "@babel/plugin-transform-modules-amd": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz", + "integrity": "sha1-7wBDXUbaCllhqnKKHS7P8GPk+5E=", "dev": true, "requires": { - "@babel/types": "^7.4.4" + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0", + "babel-plugin-dynamic-import-node": "^2.3.0" } }, - "@babel/helper-member-expression-to-functions": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz", - "integrity": "sha1-H7W47ERTqTxDnun+Ou6kqEt2tZA=", + "@babel/plugin-transform-modules-commonjs": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.5.0.tgz", + "integrity": "sha1-QlEn5gRSMTYIWO6qR6cdde3tenQ=", "dev": true, "requires": { - "@babel/types": "^7.5.5" + "@babel/helper-module-transforms": "^7.4.4", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0", + "babel-plugin-dynamic-import-node": "^2.3.0" } }, - "@babel/helper-module-imports": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", - "integrity": "sha1-lggbcRHkhtpNLNlxrRpP4hbMLj0=", + "@babel/plugin-transform-modules-systemjs": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.5.0.tgz", + "integrity": "sha1-51JmoT75QgLbKgYgl3dW9R1S0kk=", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/helper-hoist-variables": "^7.4.4", + "@babel/helper-plugin-utils": "^7.0.0", + "babel-plugin-dynamic-import-node": "^2.3.0" } }, - "@babel/helper-module-transforms": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz", - "integrity": "sha1-+E/4oJA43Lyh/UNVZhpQCTcWW0o=", + "@babel/plugin-transform-modules-umd": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz", + "integrity": "sha1-dnjOdRafCHe46yI1U4wHQmjdAa4=", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/template": "^7.4.4", - "@babel/types": "^7.5.5", - "lodash": "^4.17.13" + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" } }, - "@babel/helper-optimise-call-expression": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", - "integrity": "sha1-opIMVwKwc8Fd5REGIAqoytIEl9U=", + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.5.tgz", + "integrity": "sha1-nSaf0oo3AlgZm0KUc2gTpgu90QY=", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "regexp-tree": "^0.1.6" } }, - "@babel/helper-plugin-utils": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", - "integrity": "sha1-u7P77phmHFaQNCN8wDlnupm08lA=", - "dev": true - }, - "@babel/helper-regex": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.5.5.tgz", - "integrity": "sha1-CqaCT3EAouDonBUnwjk2wVLKs1E=", + "@babel/plugin-transform-new-target": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz", + "integrity": "sha1-GNEgQ4sMye6VpH8scryXaPvtYKU=", "dev": true, "requires": { - "lodash": "^4.17.13" + "@babel/helper-plugin-utils": "^7.0.0" } }, - "@babel/helper-remap-async-to-generator": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", - "integrity": "sha1-Nh2AghtvONp1vT8HheziCojF/n8=", + "@babel/plugin-transform-object-super": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz", + "integrity": "sha1-xwAh34NAc8ZethO4Z5zEo4HRqfk=", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-wrap-function": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.5.5" } }, - "@babel/helper-replace-supers": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz", - "integrity": "sha1-+EzkPfAxIi0rrQaNJibLV5nDS8I=", + "@babel/plugin-transform-parameters": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz", + "integrity": "sha1-dVbPA/MYvScZ/kySLS2Ai+VXHhY=", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.5.5", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/traverse": "^7.5.5", - "@babel/types": "^7.5.5" + "@babel/helper-call-delegate": "^7.4.4", + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" } }, - "@babel/helper-simple-access": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", - "integrity": "sha1-Ze65VMjCRb6qToWdphiPOdceWFw=", + "@babel/plugin-transform-regenerator": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz", + "integrity": "sha1-Yp3IJRLFXO4BNB+ye9/LIQNUaA8=", "dev": true, "requires": { - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" + "regenerator-transform": "^0.14.0" } }, - "@babel/helper-split-export-declaration": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", - "integrity": "sha1-/5SJSjQL549T8GrwOLIFxJ2ZNnc=", + "@babel/plugin-transform-runtime": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.5.5.tgz", + "integrity": "sha1-pjMa+/xZGJ0hNbLglHRFeo49KLw=", "dev": true, "requires": { - "@babel/types": "^7.4.4" + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "resolve": "^1.8.1", + "semver": "^5.5.1" } }, - "@babel/helper-wrap-function": { + "@babel/plugin-transform-shorthand-properties": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz", - "integrity": "sha1-xOABJEV2nigVtVKW6tQ6lYVJ9vo=", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz", + "integrity": "sha1-YzOu4vjW7n4oYVRXKYk0o7RhmPA=", "dev": true, "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.2.0" + "@babel/helper-plugin-utils": "^7.0.0" } }, - "@babel/helpers": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.5.5.tgz", - "integrity": "sha1-Y5CNKnOUIinR5mhbwqDnMN3jt14=", + "@babel/plugin-transform-spread": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz", + "integrity": "sha1-MQOpq+IvdCttQG7NPNSbd0kZtAY=", "dev": true, "requires": { - "@babel/template": "^7.4.4", - "@babel/traverse": "^7.5.5", - "@babel/types": "^7.5.5" + "@babel/helper-plugin-utils": "^7.0.0" } }, - "@babel/highlight": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", - "integrity": "sha1-VtETEr2SSPphlZHQJHK+boyzJUA=", + "@babel/plugin-transform-sticky-regex": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz", + "integrity": "sha1-oeRUtZlVYKnB4NU338FQYf0mh+E=", "dev": true, "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0" } }, - "@babel/parser": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", - "integrity": "sha1-AvB3rIgX099Kgy71neZ1Zeccyks=", - "dev": true - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz", - "integrity": "sha1-somzBmadzkrSCwJSiJoVdoydQX4=", + "@babel/plugin-transform-template-literals": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz", + "integrity": "sha1-nSj+p7vOY3+3YSoHUJidgyHUvLA=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0", - "@babel/plugin-syntax-async-generators": "^7.2.0" + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" } }, - "@babel/plugin-proposal-class-properties": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.5.5.tgz", - "integrity": "sha1-qXTPrh43wxEOcfPGouSLjnGVjNQ=", + "@babel/plugin-transform-typeof-symbol": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz", + "integrity": "sha1-EX0rzsL79ktLWdH5gZiUaC0p8rI=", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.5.5", "@babel/helper-plugin-utils": "^7.0.0" } }, - "@babel/plugin-proposal-decorators": { + "@babel/plugin-transform-unicode-regex": { "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.4.4.tgz", - "integrity": "sha1-3psqGoqwGW83jiqC8QtuKjbyHMA=", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz", + "integrity": "sha1-q0Y0u08U02cov1l4Mis1WHeHlw8=", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.4.4", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-decorators": "^7.2.0" + "@babel/helper-regex": "^7.4.4", + "regexpu-core": "^4.5.4" } }, - "@babel/plugin-proposal-json-strings": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", - "integrity": "sha1-Vo7MRGxhSK5rJn8CVREwiR4p8xc=", + "@babel/preset-env": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.3.4.tgz", + "integrity": "sha1-iHzzi20jyC8ZtRNSmL2xYAYuM+E=", "dev": true, "requires": { + "@babel/helper-module-imports": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-json-strings": "^7.2.0" + "@babel/plugin-proposal-async-generator-functions": "^7.2.0", + "@babel/plugin-proposal-json-strings": "^7.2.0", + "@babel/plugin-proposal-object-rest-spread": "^7.3.4", + "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.2.0", + "@babel/plugin-syntax-async-generators": "^7.2.0", + "@babel/plugin-syntax-json-strings": "^7.2.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", + "@babel/plugin-transform-arrow-functions": "^7.2.0", + "@babel/plugin-transform-async-to-generator": "^7.3.4", + "@babel/plugin-transform-block-scoped-functions": "^7.2.0", + "@babel/plugin-transform-block-scoping": "^7.3.4", + "@babel/plugin-transform-classes": "^7.3.4", + "@babel/plugin-transform-computed-properties": "^7.2.0", + "@babel/plugin-transform-destructuring": "^7.2.0", + "@babel/plugin-transform-dotall-regex": "^7.2.0", + "@babel/plugin-transform-duplicate-keys": "^7.2.0", + "@babel/plugin-transform-exponentiation-operator": "^7.2.0", + "@babel/plugin-transform-for-of": "^7.2.0", + "@babel/plugin-transform-function-name": "^7.2.0", + "@babel/plugin-transform-literals": "^7.2.0", + "@babel/plugin-transform-modules-amd": "^7.2.0", + "@babel/plugin-transform-modules-commonjs": "^7.2.0", + "@babel/plugin-transform-modules-systemjs": "^7.3.4", + "@babel/plugin-transform-modules-umd": "^7.2.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.3.0", + "@babel/plugin-transform-new-target": "^7.0.0", + "@babel/plugin-transform-object-super": "^7.2.0", + "@babel/plugin-transform-parameters": "^7.2.0", + "@babel/plugin-transform-regenerator": "^7.3.4", + "@babel/plugin-transform-shorthand-properties": "^7.2.0", + "@babel/plugin-transform-spread": "^7.2.0", + "@babel/plugin-transform-sticky-regex": "^7.2.0", + "@babel/plugin-transform-template-literals": "^7.2.0", + "@babel/plugin-transform-typeof-symbol": "^7.2.0", + "@babel/plugin-transform-unicode-regex": "^7.2.0", + "browserslist": "^4.3.4", + "invariant": "^2.2.2", + "js-levenshtein": "^1.1.3", + "semver": "^5.3.0" } }, - "@babel/plugin-proposal-object-rest-spread": { + "@babel/runtime": { "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz", - "integrity": "sha1-YZOXRPcbp2o65Gte6hilTBbSLlg=", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.5.5.tgz", + "integrity": "sha1-dPulbTXvvspEQJHHhQzNSU/S8TI=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.2.0" + "regenerator-runtime": "^0.13.2" } }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz", - "integrity": "sha1-E12B7baKCB5V5W7EhUHs6AZcOPU=", + "@babel/runtime-corejs2": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.5.5.tgz", + "integrity": "sha1-wyFMCO8gNBr0GH8cn73DV/vslrI=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.2.0" + "core-js": "^2.6.5", + "regenerator-runtime": "^0.13.2" } }, - "@babel/plugin-proposal-unicode-property-regex": { + "@babel/template": { "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz", - "integrity": "sha1-UB/9mCbAuR2iJpByByKsfLHKnHg=", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", + "integrity": "sha1-9LiNEiVomgj1vDoXSDVFvp5O0jc=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.5.4" + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.4.4", + "@babel/types": "^7.4.4" } }, - "@babel/plugin-syntax-async-generators": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz", - "integrity": "sha1-aeHw2zTG9aDPfiszI78VmnbIy38=", + "@babel/traverse": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", + "integrity": "sha1-9mT482jtMpiM1kjan3LVynDxZbs=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.5.5", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.5.5", + "@babel/types": "^7.5.5", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" } }, - "@babel/plugin-syntax-decorators": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.2.0.tgz", - "integrity": "sha1-xQsblX3MaeSxEntl4cM+72FXDBs=", + "@babel/types": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz", + "integrity": "sha1-l7n3KOGCeFkJqkq1YmTwkKAo0Yo=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" } }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz", - "integrity": "sha1-acFZ/69JmBIhYa2OvF5tH1XfhhI=", + "@hapi/address": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.0.0.tgz", + "integrity": "sha1-nwVGnIjLL9Pc1iR3a1TulcMSEmo=", + "dev": true + }, + "@hapi/hoek": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-6.2.4.tgz", + "integrity": "sha1-S5X7rMv7qQGFaQiQvfGi+72hBZU=", + "dev": true + }, + "@hapi/joi": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-15.1.0.tgz", + "integrity": "sha1-lAy3SbXFXCarOzTONi6CthYsjno=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "@hapi/address": "2.x.x", + "@hapi/hoek": "6.x.x", + "@hapi/marker": "1.x.x", + "@hapi/topo": "3.x.x" + } }, - "@babel/plugin-syntax-json-strings": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", - "integrity": "sha1-cr0T9v/h0lk4Ep0qGGsR/WKVFHA=", + "@hapi/marker": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@hapi/marker/-/marker-1.0.0.tgz", + "integrity": "sha1-ZbCysB0b4GMEiGzptLd7G/shp2k=", + "dev": true + }, + "@hapi/topo": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-3.1.2.tgz", + "integrity": "sha1-V8wTF74ajF9HwST5sOPEnNeEJNI=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@hapi/hoek": "8.x.x" + }, + "dependencies": { + "@hapi/hoek": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-8.1.0.tgz", + "integrity": "sha1-j3Ynsj7Zv2cIj8f5Zp5IxjrUIb0=", + "dev": true + } } }, - "@babel/plugin-syntax-jsx": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz", - "integrity": "sha1-C4WjtLx830zEuL8jYzW5B8oi58c=", + "@intervolga/optimize-cssnano-plugin": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@intervolga/optimize-cssnano-plugin/-/optimize-cssnano-plugin-1.0.6.tgz", + "integrity": "sha1-vnx4RhKLiPapsdEmGgrQbrXA/fg=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "cssnano": "^4.0.0", + "cssnano-preset-default": "^4.0.0", + "postcss": "^7.0.0" } }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", - "integrity": "sha1-O3o+czUQxX6CC5FCpleayLDfrS4=", + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha1-UkryQNGjYFJ7cwR17PoTRKpUDd4=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" } }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz", - "integrity": "sha1-qUAT1u2okI3+akd+f57ahWVuz1w=", + "@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha1-K1o6s/kYzKSKjHVMCBaOPwPrphs=", + "dev": true + }, + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha1-n7OjzzEyMoFR81PeRjLgHlIQK+o=", + "dev": true + }, + "@soda/friendly-errors-webpack-plugin": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.7.1.tgz", + "integrity": "sha1-cG9kvLSouWQrSK46zkRMcDNNYV0=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "chalk": "^1.1.3", + "error-stack-parser": "^2.0.0", + "string-width": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } } }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", - "integrity": "sha1-mur75Nb/xlY7+Pg3IJFijwB3lVA=", + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha1-sWZeLEYaLNkvTBu/UNVFTeDUtCE=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "defer-to-connect": "^1.0.1" } }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz", - "integrity": "sha1-iaOEigFmYjtbxIEWS1k2q5R+iH4=", + "@types/debug": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.4.tgz", + "integrity": "sha1-Vu7Edwbw/Qt8aU6uLzFy5rC3ado=", + "dev": true + }, + "@types/events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", + "integrity": "sha1-KGLz9Yqaf3w+eNefEw3U1xwlwqc=", + "dev": true + }, + "@types/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-qlmhxuP7xCHgfM0xqUTDDrpSFXU=", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0" + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" } }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz", - "integrity": "sha1-XTzBHo1d3XUqpkyRSNDbbLef0ZA=", + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha1-PcoOPzOyAPx9ETnAzZbBJoyt/Z0=", + "dev": true + }, + "@types/node": { + "version": "12.6.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.6.8.tgz", + "integrity": "sha1-5Gm0v50cmDKu5JB7qKBRSUNXwSw=", + "dev": true + }, + "@types/normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha1-5IbQ2XOW15vu3QpuM/RTT/a0lz4=", + "dev": true + }, + "@types/q": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz", + "integrity": "sha1-aQoUdbhPKohP0HzXl8APXzE1bqg=", + "dev": true + }, + "@vue/babel-helper-vue-jsx-merge-props": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.0.0.tgz", + "integrity": "sha1-BI/leZWNpAj7eosqPsBQtQpmEEA=", + "dev": true + }, + "@vue/babel-plugin-transform-vue-jsx": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-1.0.0.tgz", + "integrity": "sha1-68vznDEslBFMjE9AfuT2yXqkVDI=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-module-imports": "^7.0.0", + "@babel/plugin-syntax-jsx": "^7.2.0", + "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0", + "html-tags": "^2.0.0", + "lodash.kebabcase": "^4.1.1", + "svg-tags": "^1.0.0" } }, - "@babel/plugin-transform-block-scoping": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.5.5.tgz", - "integrity": "sha1-o185XlQCgi8Q0hGfb44EXjY5os4=", + "@vue/babel-preset-app": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@vue/babel-preset-app/-/babel-preset-app-3.9.2.tgz", + "integrity": "sha1-tyqbBqu+P48nJ4O+E5UScSd74zg=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "lodash": "^4.17.13" + "@babel/helper-module-imports": "^7.0.0", + "@babel/plugin-proposal-class-properties": "^7.0.0", + "@babel/plugin-proposal-decorators": "^7.1.0", + "@babel/plugin-syntax-dynamic-import": "^7.0.0", + "@babel/plugin-syntax-jsx": "^7.0.0", + "@babel/plugin-transform-runtime": "^7.4.0", + "@babel/preset-env": "^7.0.0 < 7.4.0", + "@babel/runtime": "^7.0.0", + "@babel/runtime-corejs2": "^7.2.0", + "@vue/babel-preset-jsx": "^1.0.0", + "babel-plugin-dynamic-import-node": "^2.2.0", + "babel-plugin-module-resolver": "3.2.0", + "core-js": "^2.6.5" } }, - "@babel/plugin-transform-classes": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz", - "integrity": "sha1-0JQpnZvWgKFKKg7a44MFrWD7Tek=", + "@vue/babel-preset-jsx": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vue/babel-preset-jsx/-/babel-preset-jsx-1.1.0.tgz", + "integrity": "sha1-yAATKfWzcil6MRGiUetPnpVsEmY=", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-define-map": "^7.5.5", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.5.5", - "@babel/helper-split-export-declaration": "^7.4.4", - "globals": "^11.1.0" + "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0", + "@vue/babel-plugin-transform-vue-jsx": "^1.0.0", + "@vue/babel-sugar-functional-vue": "^1.0.0", + "@vue/babel-sugar-inject-h": "^1.0.0", + "@vue/babel-sugar-v-model": "^1.0.0", + "@vue/babel-sugar-v-on": "^1.1.0" } }, - "@babel/plugin-transform-computed-properties": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz", - "integrity": "sha1-g6ffamWIZbHI9kHVEMbzryICFto=", + "@vue/babel-sugar-functional-vue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-functional-vue/-/babel-sugar-functional-vue-1.0.0.tgz", + "integrity": "sha1-F+LEyie3SyRNo7kjJA7JHRAEjLM=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/plugin-syntax-jsx": "^7.2.0" } }, - "@babel/plugin-transform-destructuring": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.5.0.tgz", - "integrity": "sha1-9sCf3+P5RRb/B0/od9t7ye8FhVo=", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz", - "integrity": "sha1-NhoUi8lRREMSxpRG127R6o5EUMM=", + "@vue/babel-sugar-inject-h": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-inject-h/-/babel-sugar-inject-h-1.0.0.tgz", + "integrity": "sha1-5e+2xbW3mI3AODGvbRM797zeY0c=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.5.4" + "@babel/plugin-syntax-jsx": "^7.2.0" } }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz", - "integrity": "sha1-xdv1EGv4TN9pEiLAl0wSsd+TGFM=", + "@vue/babel-sugar-v-model": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-model/-/babel-sugar-v-model-1.0.0.tgz", + "integrity": "sha1-9NpWqmf2WjSb0sJpqV5y5gGvRhM=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/plugin-syntax-jsx": "^7.2.0", + "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0", + "@vue/babel-plugin-transform-vue-jsx": "^1.0.0", + "camelcase": "^5.0.0", + "html-tags": "^2.0.0", + "svg-tags": "^1.0.0" } }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz", - "integrity": "sha1-pjhoKJ5bQAf3BU1GSRr1FDV2YAg=", + "@vue/babel-sugar-v-on": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-on/-/babel-sugar-v-on-1.1.0.tgz", + "integrity": "sha1-Hys17uq7h+r4klkx9NNP2OZASkU=", "dev": true, "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/plugin-syntax-jsx": "^7.2.0", + "@vue/babel-plugin-transform-vue-jsx": "^1.0.0", + "camelcase": "^5.0.0" } }, - "@babel/plugin-transform-for-of": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz", - "integrity": "sha1-Amf8c14kyAi6FzhmxsTRRA/DxVY=", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } + "@vue/cli-overlay": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/@vue/cli-overlay/-/cli-overlay-3.9.0.tgz", + "integrity": "sha1-EfUT0foRsBNfuLqLiNIo3w3FQuA=", + "dev": true }, - "@babel/plugin-transform-function-name": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz", - "integrity": "sha1-4UNhFquwYQwiWQlISHVKxSMJIq0=", + "@vue/cli-plugin-babel": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@vue/cli-plugin-babel/-/cli-plugin-babel-3.9.2.tgz", + "integrity": "sha1-j/lio4Oq6v0rKAmYQopX6iPpU5w=", "dev": true, "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/core": "^7.0.0", + "@vue/babel-preset-app": "^3.9.2", + "@vue/cli-shared-utils": "^3.9.0", + "babel-loader": "^8.0.5", + "webpack": ">=4 < 4.29" } }, - "@babel/plugin-transform-literals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz", - "integrity": "sha1-aQNT6B+SZ9rU/Yz9d+r6hqulPqE=", + "@vue/cli-plugin-eslint": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@vue/cli-plugin-eslint/-/cli-plugin-eslint-3.9.2.tgz", + "integrity": "sha1-dHxhaxOhHzSsgFVO7omcv80Zd7g=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@vue/cli-shared-utils": "^3.9.0", + "babel-eslint": "^10.0.1", + "eslint": "^4.19.1", + "eslint-loader": "^2.1.2", + "eslint-plugin-vue": "^4.7.1", + "globby": "^9.2.0", + "webpack": ">=4 < 4.29", + "yorkie": "^2.0.0" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "optional": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true, + "optional": true + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "optional": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "eslint": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", + "integrity": "sha1-MtHWU+HZBAiFS/spbwdux+GGowA=", + "dev": true, + "optional": true, + "requires": { + "ajv": "^5.3.0", + "babel-code-frame": "^6.22.0", + "chalk": "^2.1.0", + "concat-stream": "^1.6.0", + "cross-spawn": "^5.1.0", + "debug": "^3.1.0", + "doctrine": "^2.1.0", + "eslint-scope": "^3.7.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^3.5.4", + "esquery": "^1.0.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.0.1", + "ignore": "^3.3.3", + "imurmurhash": "^0.1.4", + "inquirer": "^3.0.6", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.9.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.4", + "minimatch": "^3.0.2", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "pluralize": "^7.0.0", + "progress": "^2.0.0", + "regexpp": "^1.0.1", + "require-uncached": "^1.0.3", + "semver": "^5.3.0", + "strip-ansi": "^4.0.0", + "strip-json-comments": "~2.0.1", + "table": "4.0.2", + "text-table": "~0.2.0" + } + }, + "eslint-plugin-vue": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-4.7.1.tgz", + "integrity": "sha1-yCm5/GJYLBiXtaC5Sv1E7MpRHmM=", + "dev": true, + "optional": true, + "requires": { + "vue-eslint-parser": "^2.0.3" + } + }, + "eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha1-u1ByANPRf2AkdjYWC0gmKEsQhTU=", + "dev": true, + "optional": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true, + "optional": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true, + "optional": true + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=", + "dev": true, + "optional": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "optional": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true, + "optional": true + } } }, - "@babel/plugin-transform-modules-amd": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz", - "integrity": "sha1-7wBDXUbaCllhqnKKHS7P8GPk+5E=", + "@vue/cli-service": { + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/@vue/cli-service/-/cli-service-3.9.3.tgz", + "integrity": "sha1-S9V4ZGWvuLYIxcf8lmE5DnR+p1Y=", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0", - "babel-plugin-dynamic-import-node": "^2.3.0" + "@intervolga/optimize-cssnano-plugin": "^1.0.5", + "@soda/friendly-errors-webpack-plugin": "^1.7.1", + "@vue/cli-overlay": "^3.9.0", + "@vue/cli-shared-utils": "^3.9.0", + "@vue/component-compiler-utils": "^2.6.0", + "@vue/preload-webpack-plugin": "^1.1.0", + "@vue/web-component-wrapper": "^1.2.0", + "acorn": "^6.1.1", + "acorn-walk": "^6.1.1", + "address": "^1.0.3", + "autoprefixer": "^9.5.1", + "browserslist": "^4.5.4", + "cache-loader": "^2.0.1", + "case-sensitive-paths-webpack-plugin": "^2.2.0", + "chalk": "^2.4.2", + "cli-highlight": "^2.1.0", + "clipboardy": "^2.0.0", + "cliui": "^5.0.0", + "copy-webpack-plugin": "^4.6.0", + "css-loader": "^1.0.1", + "cssnano": "^4.1.10", + "current-script-polyfill": "^1.0.0", + "debug": "^4.1.1", + "default-gateway": "^5.0.2", + "dotenv": "^7.0.0", + "dotenv-expand": "^5.1.0", + "escape-string-regexp": "^1.0.5", + "file-loader": "^3.0.1", + "fs-extra": "^7.0.1", + "globby": "^9.2.0", + "hash-sum": "^1.0.2", + "html-webpack-plugin": "^3.2.0", + "launch-editor-middleware": "^2.2.1", + "lodash.defaultsdeep": "^4.6.1", + "lodash.mapvalues": "^4.6.0", + "lodash.transform": "^4.6.0", + "mini-css-extract-plugin": "^0.6.0", + "minimist": "^1.2.0", + "ora": "^3.4.0", + "portfinder": "^1.0.20", + "postcss-loader": "^3.0.0", + "read-pkg": "^5.0.0", + "semver": "^6.0.0", + "slash": "^2.0.0", + "source-map-url": "^0.4.0", + "ssri": "^6.0.1", + "string.prototype.padend": "^3.0.0", + "terser-webpack-plugin": "^1.2.3", + "thread-loader": "^2.1.2", + "url-loader": "^1.1.2", + "vue-loader": "^15.7.0", + "webpack": ">=4 < 4.29", + "webpack-bundle-analyzer": "^3.3.0", + "webpack-chain": "^4.11.0", + "webpack-dev-server": "^3.4.1", + "webpack-merge": "^4.2.1" + }, + "dependencies": { + "acorn": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz", + "integrity": "sha1-PthCLW3sCeYSHMeoQ8qGozCoa1E=", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=", + "dev": true + } } }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.5.0.tgz", - "integrity": "sha1-QlEn5gRSMTYIWO6qR6cdde3tenQ=", + "@vue/cli-shared-utils": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/@vue/cli-shared-utils/-/cli-shared-utils-3.9.0.tgz", + "integrity": "sha1-y1akQ792Ooc4SaEdB+nnY4qhbMI=", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.4.4", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0", - "babel-plugin-dynamic-import-node": "^2.3.0" + "@hapi/joi": "^15.0.1", + "chalk": "^2.4.1", + "execa": "^1.0.0", + "launch-editor": "^2.2.1", + "lru-cache": "^5.1.1", + "node-ipc": "^9.1.1", + "open": "^6.3.0", + "ora": "^3.4.0", + "request": "^2.87.0", + "request-promise-native": "^1.0.7", + "semver": "^6.0.0", + "string.prototype.padstart": "^3.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=", + "dev": true + } } }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.5.0.tgz", - "integrity": "sha1-51JmoT75QgLbKgYgl3dW9R1S0kk=", + "@vue/component-compiler-utils": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-2.6.0.tgz", + "integrity": "sha1-qkbSpvdkdECwuJMkNNIvEjceVDs=", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.4.4", - "@babel/helper-plugin-utils": "^7.0.0", - "babel-plugin-dynamic-import-node": "^2.3.0" + "consolidate": "^0.15.1", + "hash-sum": "^1.0.2", + "lru-cache": "^4.1.2", + "merge-source-map": "^1.1.0", + "postcss": "^7.0.14", + "postcss-selector-parser": "^5.0.0", + "prettier": "1.16.3", + "source-map": "~0.6.1", + "vue-template-es2015-compiler": "^1.9.0" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } } }, - "@babel/plugin-transform-modules-umd": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz", - "integrity": "sha1-dnjOdRafCHe46yI1U4wHQmjdAa4=", + "@vue/preload-webpack-plugin": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vue/preload-webpack-plugin/-/preload-webpack-plugin-1.1.0.tgz", + "integrity": "sha1-12jboAQmHAKbU6d8XqLV+e5PPM4=", + "dev": true, + "requires": {} + }, + "@vue/web-component-wrapper": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@vue/web-component-wrapper/-/web-component-wrapper-1.2.0.tgz", + "integrity": "sha1-uw5G8VhafiibTuYGfcxaauYvHdE=", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.11.tgz", + "integrity": "sha1-uYhYLK+7Kwlei1VlJvMMkNBXys4=", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@webassemblyjs/helper-module-context": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/wast-parser": "1.7.11" } }, - "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.5.tgz", - "integrity": "sha1-nSaf0oo3AlgZm0KUc2gTpgu90QY=", + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.11.tgz", + "integrity": "sha1-pp8K9lAuuaPARVVbGmEp09Py4xM=", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.11.tgz", + "integrity": "sha1-x7a7gQX4QDlRGis5zklPGTgYoyo=", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.11.tgz", + "integrity": "sha1-MSLUjcxslFbtmC3r4WyPNxAd85s=", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.11.tgz", + "integrity": "sha1-z48QbnRmYqDaKb3vY1/NPRJINks=", "dev": true, "requires": { - "regexp-tree": "^0.1.6" + "@webassemblyjs/wast-printer": "1.7.11" } }, - "@babel/plugin-transform-new-target": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz", - "integrity": "sha1-GNEgQ4sMye6VpH8scryXaPvtYKU=", + "@webassemblyjs/helper-fsm": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.11.tgz", + "integrity": "sha1-3ziIKmJAgNA/dQP5Pj8XrFrAEYE=", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.11.tgz", + "integrity": "sha1-2HTXIuUeYqwgJHaTXWScgC+g4gk=", + "dev": true + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.11.tgz", + "integrity": "sha1-3ZoegX8cLrEFtM8QEwk8ufPJywY=", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.11.tgz", + "integrity": "sha1-nJrEHs+fvP/8lvbSZ14t4zgR5oo=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-buffer": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/wasm-gen": "1.7.11" } }, - "@babel/plugin-transform-object-super": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz", - "integrity": "sha1-xwAh34NAc8ZethO4Z5zEo4HRqfk=", + "@webassemblyjs/ieee754": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.7.11.tgz", + "integrity": "sha1-yVg562N1ejGICq7HtlEtQZGsZAs=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.5.5" + "@xtuc/ieee754": "^1.2.0" } }, - "@babel/plugin-transform-parameters": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz", - "integrity": "sha1-dVbPA/MYvScZ/kySLS2Ai+VXHhY=", + "@webassemblyjs/leb128": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.7.11.tgz", + "integrity": "sha1-1yZ6HunEWU/T9+NymIGOxlaH22M=", "dev": true, "requires": { - "@babel/helper-call-delegate": "^7.4.4", - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@xtuc/long": "4.2.1" } }, - "@babel/plugin-transform-regenerator": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz", - "integrity": "sha1-Yp3IJRLFXO4BNB+ye9/LIQNUaA8=", + "@webassemblyjs/utf8": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.7.11.tgz", + "integrity": "sha1-Btchjqn9yUpnk6qSIIFg2z0m7oI=", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.11.tgz", + "integrity": "sha1-jHTKR01PlR0B266b1wgU7iKoIAU=", "dev": true, "requires": { - "regenerator-transform": "^0.14.0" + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-buffer": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/helper-wasm-section": "1.7.11", + "@webassemblyjs/wasm-gen": "1.7.11", + "@webassemblyjs/wasm-opt": "1.7.11", + "@webassemblyjs/wasm-parser": "1.7.11", + "@webassemblyjs/wast-printer": "1.7.11" } }, - "@babel/plugin-transform-runtime": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.5.5.tgz", - "integrity": "sha1-pjMa+/xZGJ0hNbLglHRFeo49KLw=", + "@webassemblyjs/wasm-gen": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.11.tgz", + "integrity": "sha1-m7upQvIjdWhqb7dZr816ycRdoag=", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "resolve": "^1.8.1", - "semver": "^5.5.1" + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/ieee754": "1.7.11", + "@webassemblyjs/leb128": "1.7.11", + "@webassemblyjs/utf8": "1.7.11" } }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz", - "integrity": "sha1-YzOu4vjW7n4oYVRXKYk0o7RhmPA=", + "@webassemblyjs/wasm-opt": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.11.tgz", + "integrity": "sha1-szHo5874+OLwB9QsOjagWAp9bKc=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-buffer": "1.7.11", + "@webassemblyjs/wasm-gen": "1.7.11", + "@webassemblyjs/wasm-parser": "1.7.11" } }, - "@babel/plugin-transform-spread": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz", - "integrity": "sha1-MQOpq+IvdCttQG7NPNSbd0kZtAY=", + "@webassemblyjs/wasm-parser": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.11.tgz", + "integrity": "sha1-bj0g+mo1GfawhO+Tka1YIR77Cho=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-api-error": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/ieee754": "1.7.11", + "@webassemblyjs/leb128": "1.7.11", + "@webassemblyjs/utf8": "1.7.11" } }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz", - "integrity": "sha1-oeRUtZlVYKnB4NU338FQYf0mh+E=", + "@webassemblyjs/wast-parser": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.7.11.tgz", + "integrity": "sha1-Jb0RdWLKjAAnIP+BFu+QctnKhpw=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0" + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/floating-point-hex-parser": "1.7.11", + "@webassemblyjs/helper-api-error": "1.7.11", + "@webassemblyjs/helper-code-frame": "1.7.11", + "@webassemblyjs/helper-fsm": "1.7.11", + "@xtuc/long": "4.2.1" } }, - "@babel/plugin-transform-template-literals": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz", - "integrity": "sha1-nSj+p7vOY3+3YSoHUJidgyHUvLA=", + "@webassemblyjs/wast-printer": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.7.11.tgz", + "integrity": "sha1-xCRbbeJCy1CizJUBdP2/ZceNeBM=", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/wast-parser": "1.7.11", + "@xtuc/long": "4.2.1" } }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz", - "integrity": "sha1-EX0rzsL79ktLWdH5gZiUaC0p8rI=", - "dev": true, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha1-7vAUoxRa5Hehy8AM0eVSM23Ot5A=", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.1.tgz", + "integrity": "sha1-XIXWYvdvodNFdXZsXc1mFavNMNg=", + "dev": true + }, + "@zeit/schemas": { + "version": "2.36.0", + "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.36.0.tgz", + "integrity": "sha512-7kjMwcChYEzMKjeex9ZFXkt1AyNov9R5HZtjBKVsmVpw7pa7ZtlCGvCBC2vnnXctaYN+aRI61HjIqeetZW5ROg==", + "dev": true + }, + "7zip-bin": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-4.1.0.tgz", + "integrity": "sha1-M+/2YqXDnAwgYRcMwAPFEgdD//A=", + "dev": true + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha1-UxvHJlF6OytB+FACHGzBXqq1B80=", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "mime-types": "~2.1.24", + "negotiator": "0.6.2" } }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz", - "integrity": "sha1-q0Y0u08U02cov1l4Mis1WHeHlw8=", + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha1-Z6ojG/iBKXS4UjWpZ3Hra9B+onk=", + "dev": true + }, + "acorn-dynamic-import": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz", + "integrity": "sha1-kBzu5Mf6rvfgetKkfokGddpQong=", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.5.4" + "acorn": "^5.0.0" } }, - "@babel/preset-env": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.3.4.tgz", - "integrity": "sha1-iHzzi20jyC8ZtRNSmL2xYAYuM+E=", + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, + "optional": true, "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-async-generator-functions": "^7.2.0", - "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.3.4", - "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.2.0", - "@babel/plugin-syntax-async-generators": "^7.2.0", - "@babel/plugin-syntax-json-strings": "^7.2.0", - "@babel/plugin-syntax-object-rest-spread": "^7.2.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", - "@babel/plugin-transform-arrow-functions": "^7.2.0", - "@babel/plugin-transform-async-to-generator": "^7.3.4", - "@babel/plugin-transform-block-scoped-functions": "^7.2.0", - "@babel/plugin-transform-block-scoping": "^7.3.4", - "@babel/plugin-transform-classes": "^7.3.4", - "@babel/plugin-transform-computed-properties": "^7.2.0", - "@babel/plugin-transform-destructuring": "^7.2.0", - "@babel/plugin-transform-dotall-regex": "^7.2.0", - "@babel/plugin-transform-duplicate-keys": "^7.2.0", - "@babel/plugin-transform-exponentiation-operator": "^7.2.0", - "@babel/plugin-transform-for-of": "^7.2.0", - "@babel/plugin-transform-function-name": "^7.2.0", - "@babel/plugin-transform-literals": "^7.2.0", - "@babel/plugin-transform-modules-amd": "^7.2.0", - "@babel/plugin-transform-modules-commonjs": "^7.2.0", - "@babel/plugin-transform-modules-systemjs": "^7.3.4", - "@babel/plugin-transform-modules-umd": "^7.2.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.3.0", - "@babel/plugin-transform-new-target": "^7.0.0", - "@babel/plugin-transform-object-super": "^7.2.0", - "@babel/plugin-transform-parameters": "^7.2.0", - "@babel/plugin-transform-regenerator": "^7.3.4", - "@babel/plugin-transform-shorthand-properties": "^7.2.0", - "@babel/plugin-transform-spread": "^7.2.0", - "@babel/plugin-transform-sticky-regex": "^7.2.0", - "@babel/plugin-transform-template-literals": "^7.2.0", - "@babel/plugin-transform-typeof-symbol": "^7.2.0", - "@babel/plugin-transform-unicode-regex": "^7.2.0", - "browserslist": "^4.3.4", - "invariant": "^2.2.2", - "js-levenshtein": "^1.1.3", - "semver": "^5.3.0" + "acorn": "^3.0.4" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true, + "optional": true + } } }, - "@babel/runtime": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.5.5.tgz", - "integrity": "sha1-dPulbTXvvspEQJHHhQzNSU/S8TI=", + "acorn-walk": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha1-Ejy487hMIXHx9/slJhWxx4prGow=", + "dev": true + }, + "address": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/address/-/address-1.1.0.tgz", + "integrity": "sha1-744EeEf80sW29QwWll+ST9mf5wk=", + "dev": true + }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" + }, + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha1-086gTWsBeyiUrWkED+yLYj60vVI=", "dev": true, "requires": { - "regenerator-runtime": "^0.13.2" + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "@babel/runtime-corejs2": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.5.5.tgz", - "integrity": "sha1-wyFMCO8gNBr0GH8cn73DV/vslrI=", + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha1-81mGrOuRr63sQQL72FAUlQzvpk0=", "dev": true, - "requires": { - "core-js": "^2.6.5", - "regenerator-runtime": "^0.13.2" - } + "requires": {} }, - "@babel/template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", - "integrity": "sha1-9LiNEiVomgj1vDoXSDVFvp5O0jc=", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.4.4", - "@babel/types": "^7.4.4" - } - }, - "@babel/traverse": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", - "integrity": "sha1-9mT482jtMpiM1kjan3LVynDxZbs=", - "dev": true, - "requires": { - "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.5.5", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.5.5", - "@babel/types": "^7.5.5", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" - } - }, - "@babel/types": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz", - "integrity": "sha1-l7n3KOGCeFkJqkq1YmTwkKAo0Yo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "@hapi/address": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.0.0.tgz", - "integrity": "sha1-nwVGnIjLL9Pc1iR3a1TulcMSEmo=", - "dev": true - }, - "@hapi/hoek": { - "version": "6.2.4", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-6.2.4.tgz", - "integrity": "sha1-S5X7rMv7qQGFaQiQvfGi+72hBZU=", - "dev": true - }, - "@hapi/joi": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-15.1.0.tgz", - "integrity": "sha1-lAy3SbXFXCarOzTONi6CthYsjno=", - "dev": true, - "requires": { - "@hapi/address": "2.x.x", - "@hapi/hoek": "6.x.x", - "@hapi/marker": "1.x.x", - "@hapi/topo": "3.x.x" - } - }, - "@hapi/marker": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@hapi/marker/-/marker-1.0.0.tgz", - "integrity": "sha1-ZbCysB0b4GMEiGzptLd7G/shp2k=", - "dev": true - }, - "@hapi/topo": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-3.1.2.tgz", - "integrity": "sha1-V8wTF74ajF9HwST5sOPEnNeEJNI=", - "dev": true, - "requires": { - "@hapi/hoek": "8.x.x" - }, - "dependencies": { - "@hapi/hoek": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-8.1.0.tgz", - "integrity": "sha1-j3Ynsj7Zv2cIj8f5Zp5IxjrUIb0=", - "dev": true - } - } - }, - "@intervolga/optimize-cssnano-plugin": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@intervolga/optimize-cssnano-plugin/-/optimize-cssnano-plugin-1.0.6.tgz", - "integrity": "sha1-vnx4RhKLiPapsdEmGgrQbrXA/fg=", - "dev": true, - "requires": { - "cssnano": "^4.0.0", - "cssnano-preset-default": "^4.0.0", - "postcss": "^7.0.0" - } - }, - "@mrmlnc/readdir-enhanced": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", - "integrity": "sha1-UkryQNGjYFJ7cwR17PoTRKpUDd4=", + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha1-75FuJxxkrBIXH9g4TqrmsjRYVNo=", "dev": true, - "requires": { - "call-me-maybe": "^1.0.1", - "glob-to-regexp": "^0.3.0" - } - }, - "@nodelib/fs.stat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", - "integrity": "sha1-K1o6s/kYzKSKjHVMCBaOPwPrphs=", - "dev": true + "requires": {} }, - "@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha1-n7OjzzEyMoFR81PeRjLgHlIQK+o=", + "alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", "dev": true }, - "@soda/friendly-errors-webpack-plugin": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.7.1.tgz", - "integrity": "sha1-cG9kvLSouWQrSK46zkRMcDNNYV0=", + "ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", "dev": true, "requires": { - "chalk": "^1.1.3", - "error-stack-parser": "^2.0.0", - "string-width": "^2.0.0" + "string-width": "^4.1.0" }, "dependencies": { "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" } }, "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "^5.0.1" } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true } } }, - "@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha1-sWZeLEYaLNkvTBu/UNVFTeDUtCE=", - "dev": true, - "requires": { - "defer-to-connect": "^1.0.1" - } + "ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha1-46PaS/uubIapwoViXeEkojQCb78=", + "dev": true }, - "@types/debug": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.4.tgz", - "integrity": "sha1-Vu7Edwbw/Qt8aU6uLzFy5rC3ado=", + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha1-h4C5j/nb9WOBUtHx/lwde0RCl2s=", "dev": true }, - "@types/events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", - "integrity": "sha1-KGLz9Yqaf3w+eNefEw3U1xwlwqc=", + "ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", "dev": true }, - "@types/glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", - "integrity": "sha1-qlmhxuP7xCHgfM0xqUTDDrpSFXU=", + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha1-i5+PCM8ay4Q3Vqg5yox+MWjFGZc=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", "dev": true, "requires": { - "@types/events": "*", - "@types/minimatch": "*", - "@types/node": "*" + "color-convert": "^1.9.0" } }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha1-PcoOPzOyAPx9ETnAzZbBJoyt/Z0=", - "dev": true - }, - "@types/node": { - "version": "12.6.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.6.8.tgz", - "integrity": "sha1-5Gm0v50cmDKu5JB7qKBRSUNXwSw=", - "dev": true - }, - "@types/normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha1-5IbQ2XOW15vu3QpuM/RTT/a0lz4=", + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", "dev": true }, - "@types/q": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz", - "integrity": "sha1-aQoUdbhPKohP0HzXl8APXzE1bqg=", - "dev": true - }, - "@vue/babel-helper-vue-jsx-merge-props": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.0.0.tgz", - "integrity": "sha1-BI/leZWNpAj7eosqPsBQtQpmEEA=", - "dev": true - }, - "@vue/babel-plugin-transform-vue-jsx": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@vue/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-1.0.0.tgz", - "integrity": "sha1-68vznDEslBFMjE9AfuT2yXqkVDI=", + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha1-vLJLTzeTTZqnrBe0ra+J58du8us=", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/plugin-syntax-jsx": "^7.2.0", - "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0", - "html-tags": "^2.0.0", - "lodash.kebabcase": "^4.1.1", - "svg-tags": "^1.0.0" + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } } }, - "@vue/babel-preset-app": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@vue/babel-preset-app/-/babel-preset-app-3.9.2.tgz", - "integrity": "sha1-tyqbBqu+P48nJ4O+E5UScSd74zg=", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/plugin-proposal-class-properties": "^7.0.0", - "@babel/plugin-proposal-decorators": "^7.1.0", - "@babel/plugin-syntax-dynamic-import": "^7.0.0", - "@babel/plugin-syntax-jsx": "^7.0.0", - "@babel/plugin-transform-runtime": "^7.4.0", - "@babel/preset-env": "^7.0.0 < 7.4.0", - "@babel/runtime": "^7.0.0", - "@babel/runtime-corejs2": "^7.2.0", - "@vue/babel-preset-jsx": "^1.0.0", - "babel-plugin-dynamic-import-node": "^2.2.0", - "babel-plugin-module-resolver": "3.2.0", - "core-js": "^2.6.5" - } + "app-builder-bin": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-2.7.1.tgz", + "integrity": "sha1-n2kK9lCTghuKYUmqKc6fjIH8VUw=", + "dev": true }, - "@vue/babel-preset-jsx": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@vue/babel-preset-jsx/-/babel-preset-jsx-1.1.0.tgz", - "integrity": "sha1-yAATKfWzcil6MRGiUetPnpVsEmY=", + "app-builder-lib": { + "version": "20.44.4", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-20.44.4.tgz", + "integrity": "sha1-OawgsxVeGwwkmYYrzeqHm1A4lXM=", "dev": true, "requires": { - "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0", - "@vue/babel-plugin-transform-vue-jsx": "^1.0.0", - "@vue/babel-sugar-functional-vue": "^1.0.0", - "@vue/babel-sugar-inject-h": "^1.0.0", - "@vue/babel-sugar-v-model": "^1.0.0", - "@vue/babel-sugar-v-on": "^1.1.0" + "7zip-bin": "~4.1.0", + "app-builder-bin": "2.7.1", + "async-exit-hook": "^2.0.1", + "bluebird-lst": "^1.0.9", + "builder-util": "10.1.2", + "builder-util-runtime": "8.2.5", + "chromium-pickle-js": "^0.2.0", + "debug": "^4.1.1", + "ejs": "^2.6.2", + "electron-osx-sign": "0.4.11", + "electron-publish": "20.44.4", + "fs-extra-p": "^8.0.2", + "hosted-git-info": "^2.7.1", + "is-ci": "^2.0.0", + "isbinaryfile": "^4.0.1", + "js-yaml": "^3.13.1", + "lazy-val": "^1.0.4", + "minimatch": "^3.0.4", + "normalize-package-data": "^2.5.0", + "plist": "^3.0.1", + "read-config-file": "3.2.2", + "sanitize-filename": "^1.6.1", + "semver": "^6.1.1", + "temp-file": "^3.3.3" + }, + "dependencies": { + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha1-Z6npZL4xpR4V5QENWObxKDQAL0Y=", + "dev": true + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha1-a8YzQYGBDgS1wis9WJ/cpVAmQEw=", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=", + "dev": true + } } }, - "@vue/babel-sugar-functional-vue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-functional-vue/-/babel-sugar-functional-vue-1.0.0.tgz", - "integrity": "sha1-F+LEyie3SyRNo7kjJA7JHRAEjLM=", + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha1-aALmJk79GMeQobDVF/DyYnvyyUo=", + "dev": true + }, + "arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "dev": true + }, + "archiver": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", + "integrity": "sha1-/2YrSnggFJSj7lRNOjP+dJZQnrw=", "dev": true, "requires": { - "@babel/plugin-syntax-jsx": "^7.2.0" + "archiver-utils": "^1.3.0", + "async": "^2.0.0", + "buffer-crc32": "^0.2.1", + "glob": "^7.0.0", + "lodash": "^4.8.0", + "readable-stream": "^2.0.0", + "tar-stream": "^1.5.0", + "zip-stream": "^1.2.0" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha1-1yYl4jRKNlbjo61Pp0n6gymdgv8=", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + } } }, - "@vue/babel-sugar-inject-h": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-inject-h/-/babel-sugar-inject-h-1.0.0.tgz", - "integrity": "sha1-5e+2xbW3mI3AODGvbRM797zeY0c=", + "archiver-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz", + "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=", "dev": true, "requires": { - "@babel/plugin-syntax-jsx": "^7.2.0" + "glob": "^7.0.0", + "graceful-fs": "^4.1.0", + "lazystream": "^1.0.0", + "lodash": "^4.8.0", + "normalize-path": "^2.0.0", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } } }, - "@vue/babel-sugar-v-model": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-model/-/babel-sugar-v-model-1.0.0.tgz", - "integrity": "sha1-9NpWqmf2WjSb0sJpqV5y5gGvRhM=", + "arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=", "dev": true, "requires": { - "@babel/plugin-syntax-jsx": "^7.2.0", - "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0", - "@vue/babel-plugin-transform-vue-jsx": "^1.0.0", - "camelcase": "^5.0.0", - "html-tags": "^2.0.0", - "svg-tags": "^1.0.0" + "sprintf-js": "~1.0.2" } }, - "@vue/babel-sugar-v-on": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-on/-/babel-sugar-v-on-1.1.0.tgz", - "integrity": "sha1-Hys17uq7h+r4klkx9NNP2OZASkU=", - "dev": true, - "requires": { - "@babel/plugin-syntax-jsx": "^7.2.0", - "@vue/babel-plugin-transform-vue-jsx": "^1.0.0", - "camelcase": "^5.0.0" - } + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=", + "dev": true }, - "@vue/cli-overlay": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@vue/cli-overlay/-/cli-overlay-3.9.0.tgz", - "integrity": "sha1-EfUT0foRsBNfuLqLiNIo3w3FQuA=", + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, - "@vue/cli-plugin-babel": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-babel/-/cli-plugin-babel-3.9.2.tgz", - "integrity": "sha1-j/lio4Oq6v0rKAmYQopX6iPpU5w=", - "dev": true, - "requires": { - "@babel/core": "^7.0.0", - "@vue/babel-preset-app": "^3.9.2", - "@vue/cli-shared-utils": "^3.9.0", - "babel-loader": "^8.0.5", - "webpack": ">=4 < 4.29" - } + "array-filter": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", + "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", + "dev": true }, - "@vue/cli-plugin-eslint": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-eslint/-/cli-plugin-eslint-3.9.2.tgz", - "integrity": "sha1-dHxhaxOhHzSsgFVO7omcv80Zd7g=", + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "array-map": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", + "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", + "dev": true + }, + "array-reduce": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", + "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", "dev": true, "requires": { - "@vue/cli-shared-utils": "^3.9.0", - "babel-eslint": "^10.0.1", - "eslint": "^4.19.1", - "eslint-loader": "^2.1.2", - "eslint-plugin-vue": "^4.7.1", - "globby": "^9.2.0", - "webpack": ">=4 < 4.29", - "yorkie": "^2.0.0" + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha1-jSR136tVO7M+d7VOWeiAu4ziMTY=", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha1-ucK/WAXx5kqt7tbfOiv6+1pz9aA=", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha1-VcEJqvbgrv2z3EtxJAxwv1dLGOs=", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" }, "dependencies": { - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", "dev": true, - "optional": true, "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "inherits": "2.0.1" } - }, + } + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha1-bIw/uCfdQ+45GPJ7gngqt2WKb9k=", + "dev": true + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha1-tyfb+H12UWAvBvTUrDh/R9kbDL8=", + "dev": true + }, + "async-exit-hook": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", + "integrity": "sha1-i9iwJLDsmxwBzMua+dspvXF9+vM=", + "dev": true + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha1-ePrtjD0HSrgfIrTphdeehzj3IPg=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha1-bZUX654DDSQ2ZmZR6GvZ9vE1M8k=", + "dev": true + }, + "autoprefixer": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.6.1.tgz", + "integrity": "sha1-UZZ6AtLSMAuwGGbBYR7INI01Wkc=", + "dev": true, + "requires": { + "browserslist": "^4.6.3", + "caniuse-lite": "^1.0.30000980", + "chalk": "^2.4.2", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^7.0.17", + "postcss-value-parser": "^4.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.0.tgz", + "integrity": "sha1-mamD02X3sq2ND5uMMJSSbqtLk20=", + "dev": true + } + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha1-8OAD2cqef1nHpQiUXXsu+aBKVC8=", + "dev": true + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true, - "optional": true + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, - "optional": true, "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, - "optional": true, "requires": { - "ms": "^2.1.1" + "ansi-regex": "^2.0.0" } }, - "eslint": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", - "integrity": "sha1-MtHWU+HZBAiFS/spbwdux+GGowA=", + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "babel-eslint": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.2.tgz", + "integrity": "sha1-GC1awgRXn/CIFoSwQFYP3MFVhFY=", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "^1.0.0" + }, + "dependencies": { + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", "dev": true, - "optional": true, "requires": { - "ajv": "^5.3.0", - "babel-code-frame": "^6.22.0", - "chalk": "^2.1.0", - "concat-stream": "^1.6.0", - "cross-spawn": "^5.1.0", - "debug": "^3.1.0", - "doctrine": "^2.1.0", - "eslint-scope": "^3.7.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^3.5.4", - "esquery": "^1.0.0", - "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", - "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.0.1", - "ignore": "^3.3.3", - "imurmurhash": "^0.1.4", - "inquirer": "^3.0.6", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.9.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.4", - "minimatch": "^3.0.2", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", - "pluralize": "^7.0.0", - "progress": "^2.0.0", - "regexpp": "^1.0.1", - "require-uncached": "^1.0.3", - "semver": "^5.3.0", - "strip-ansi": "^4.0.0", - "strip-json-comments": "~2.0.1", - "table": "4.0.2", - "text-table": "~0.2.0" + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" } - }, - "eslint-plugin-vue": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-4.7.1.tgz", - "integrity": "sha1-yCm5/GJYLBiXtaC5Sv1E7MpRHmM=", + } + } + }, + "babel-loader": { + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.6.tgz", + "integrity": "sha1-4zvbbzYrA/S7FBoMIauHxQG3Dfs=", + "dev": true, + "requires": { + "find-cache-dir": "^2.0.0", + "loader-utils": "^1.0.2", + "mkdirp": "^0.5.1", + "pify": "^4.0.1" + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", + "integrity": "sha1-8A9Qe9qjw+P/bn5emNkKesq5b38=", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-module-resolver": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-3.2.0.tgz", + "integrity": "sha1-3fpeMB47mqEthSqZefGLN4gf9ac=", + "dev": true, + "requires": { + "find-babel-config": "^1.1.0", + "glob": "^7.1.2", + "pkg-up": "^2.0.0", + "reselect": "^3.0.1", + "resolve": "^1.4.0" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha1-vgWtf5v30i4Fb5cmzuUBf78Z4uk=", + "dev": true + } + } + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, - "optional": true, "requires": { - "vue-eslint-parser": "^2.0.3" + "is-descriptor": "^1.0.0" } }, - "eslint-scope": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", - "integrity": "sha1-u1ByANPRf2AkdjYWC0gmKEsQhTU=", + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, - "optional": true, "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" + "kind-of": "^6.0.0" } }, - "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true, - "optional": true - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true, - "optional": true - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=", + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, - "optional": true, "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "kind-of": "^6.0.0" } }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, - "optional": true, "requires": { - "ansi-regex": "^3.0.0" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true, - "optional": true } } }, - "@vue/cli-service": { - "version": "3.9.3", - "resolved": "https://registry.npmjs.org/@vue/cli-service/-/cli-service-3.9.3.tgz", - "integrity": "sha1-S9V4ZGWvuLYIxcf8lmE5DnR+p1Y=", + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha1-yrHmEY8FEJXli1KBrqjBzSK/wOM=", + "dev": true + }, + "base64id": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=" + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "dev": true, "requires": { - "@intervolga/optimize-cssnano-plugin": "^1.0.5", - "@soda/friendly-errors-webpack-plugin": "^1.7.1", - "@vue/cli-overlay": "^3.9.0", - "@vue/cli-shared-utils": "^3.9.0", - "@vue/component-compiler-utils": "^2.6.0", - "@vue/preload-webpack-plugin": "^1.1.0", - "@vue/web-component-wrapper": "^1.2.0", - "acorn": "^6.1.1", - "acorn-walk": "^6.1.1", - "address": "^1.0.3", - "autoprefixer": "^9.5.1", - "browserslist": "^4.5.4", - "cache-loader": "^2.0.1", - "case-sensitive-paths-webpack-plugin": "^2.2.0", - "chalk": "^2.4.2", - "cli-highlight": "^2.1.0", - "clipboardy": "^2.0.0", - "cliui": "^5.0.0", - "copy-webpack-plugin": "^4.6.0", - "css-loader": "^1.0.1", - "cssnano": "^4.1.10", - "current-script-polyfill": "^1.0.0", - "debug": "^4.1.1", - "default-gateway": "^5.0.2", - "dotenv": "^7.0.0", - "dotenv-expand": "^5.1.0", - "escape-string-regexp": "^1.0.5", - "file-loader": "^3.0.1", - "fs-extra": "^7.0.1", - "globby": "^9.2.0", - "hash-sum": "^1.0.2", - "html-webpack-plugin": "^3.2.0", - "launch-editor-middleware": "^2.2.1", - "lodash.defaultsdeep": "^4.6.1", - "lodash.mapvalues": "^4.6.0", - "lodash.transform": "^4.6.0", - "mini-css-extract-plugin": "^0.6.0", - "minimist": "^1.2.0", - "ora": "^3.4.0", - "portfinder": "^1.0.20", - "postcss-loader": "^3.0.0", - "read-pkg": "^5.0.0", - "semver": "^6.0.0", - "slash": "^2.0.0", - "source-map-url": "^0.4.0", - "ssri": "^6.0.1", - "string.prototype.padend": "^3.0.0", - "terser-webpack-plugin": "^1.2.3", - "thread-loader": "^2.1.2", - "url-loader": "^1.1.2", - "vue-loader": "^15.7.0", - "webpack": ">=4 < 4.29", - "webpack-bundle-analyzer": "^3.3.0", - "webpack-chain": "^4.11.0", - "webpack-dev-server": "^3.4.1", - "webpack-merge": "^4.2.1" + "tweetnacl": "^0.14.3" + } + }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "requires": { + "callsite": "1.0.0" + } + }, + "bfj": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.2.tgz", + "integrity": "sha1-MlyGGoIryzWKQceKM7jm4ght3n8=", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "check-types": "^8.0.3", + "hoopy": "^0.1.4", + "tryer": "^1.0.1" + } + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha1-ZfCvOC9Xi83HQr2cKB6cstd2gyg=", + "dev": true + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha1-WYr+VHVbKGilMw0q/51Ou1Mgm2U=", + "dev": true + }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha1-oWCRFxcQPAdBDO9j71Gzl8Alr5w=", + "dev": true, + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "blob": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" + }, + "bluebird": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz", + "integrity": "sha1-qNCv1zJR7/u9X+OEp31zADwXpx8=", + "dev": true + }, + "bluebird-lst": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz", + "integrity": "sha1-pkoOQ2Vli5q1/odeud+2lBibtBw=", + "dev": true, + "requires": { + "bluebird": "^3.5.5" + } + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha1-LN4J617jQfSEdGuwMJsyU7GxRC8=", + "dev": true + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha1-lrJwnlfJxOCab9Zqj9l5hE9p8Io=", + "dev": true, + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" }, "dependencies": { - "acorn": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz", - "integrity": "sha1-PthCLW3sCeYSHMeoQ8qGozCoa1E=", + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=", + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha1-QdwaAV49WB8WIXdr4xr7KHapsbw=", "dev": true } } }, - "@vue/cli-shared-utils": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@vue/cli-shared-utils/-/cli-shared-utils-3.9.0.tgz", - "integrity": "sha1-y1akQ792Ooc4SaEdB+nnY4qhbMI=", + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", "dev": true, "requires": { - "@hapi/joi": "^15.0.1", - "chalk": "^2.4.1", - "execa": "^1.0.0", - "launch-editor": "^2.2.1", - "lru-cache": "^5.1.1", - "node-ipc": "^9.1.1", - "open": "^6.3.0", - "ora": "^3.4.0", - "request": "^2.87.0", - "request-promise-native": "^1.0.7", - "semver": "^6.0.0", - "string.prototype.padstart": "^3.0.0" + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" }, "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=", + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha1-JO+AoowaiTYX4hSbDG0NeIKTsJk=", "dev": true } } }, - "@vue/component-compiler-utils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-2.6.0.tgz", - "integrity": "sha1-qkbSpvdkdECwuJMkNNIvEjceVDs=", + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "boxen": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-3.2.0.tgz", + "integrity": "sha1-+9/w3pNjarRFCIa2/0W5LQmPRes=", "dev": true, "requires": { - "consolidate": "^0.15.1", - "hash-sum": "^1.0.2", - "lru-cache": "^4.1.2", - "merge-source-map": "^1.1.0", - "postcss": "^7.0.14", - "postcss-selector-parser": "^5.0.0", - "prettier": "1.16.3", - "source-map": "~0.6.1", - "vue-template-es2015-compiler": "^1.9.0" + "ansi-align": "^3.0.0", + "camelcase": "^5.3.1", + "chalk": "^2.4.2", + "cli-boxes": "^2.2.0", + "string-width": "^3.0.0", + "term-size": "^1.2.0", + "type-fest": "^0.3.0", + "widest-line": "^2.0.0" }, "dependencies": { - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=", + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha1-InZ74htirxCBV0MG9prFG2IgOWE=", "dev": true, "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" } }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha1-Y9ANIE4FlHT+Xht8ARESu9HcKeE=", "dev": true } } }, - "@vue/preload-webpack-plugin": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@vue/preload-webpack-plugin/-/preload-webpack-plugin-1.1.0.tgz", - "integrity": "sha1-12jboAQmHAKbU6d8XqLV+e5PPM4=", - "dev": true, - "requires": {} - }, - "@vue/web-component-wrapper": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@vue/web-component-wrapper/-/web-component-wrapper-1.2.0.tgz", - "integrity": "sha1-uw5G8VhafiibTuYGfcxaauYvHdE=", - "dev": true - }, - "@webassemblyjs/ast": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.11.tgz", - "integrity": "sha1-uYhYLK+7Kwlei1VlJvMMkNBXys4=", + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", "dev": true, "requires": { - "@webassemblyjs/helper-module-context": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/wast-parser": "1.7.11" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.11.tgz", - "integrity": "sha1-pp8K9lAuuaPARVVbGmEp09Py4xM=", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.11.tgz", - "integrity": "sha1-x7a7gQX4QDlRGis5zklPGTgYoyo=", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.11.tgz", - "integrity": "sha1-MSLUjcxslFbtmC3r4WyPNxAd85s=", - "dev": true - }, - "@webassemblyjs/helper-code-frame": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.11.tgz", - "integrity": "sha1-z48QbnRmYqDaKb3vY1/NPRJINks=", + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=", "dev": true, "requires": { - "@webassemblyjs/wast-printer": "1.7.11" + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } } }, - "@webassemblyjs/helper-fsm": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.11.tgz", - "integrity": "sha1-3ziIKmJAgNA/dQP5Pj8XrFrAEYE=", - "dev": true - }, - "@webassemblyjs/helper-module-context": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.11.tgz", - "integrity": "sha1-2HTXIuUeYqwgJHaTXWScgC+g4gk=", - "dev": true - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.11.tgz", - "integrity": "sha1-3ZoegX8cLrEFtM8QEwk8ufPJywY=", + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", "dev": true }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.11.tgz", - "integrity": "sha1-nJrEHs+fvP/8lvbSZ14t4zgR5oo=", + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha1-Mmc0ZC9APavDADIJhTu3CtQo70g=", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-buffer": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/wasm-gen": "1.7.11" + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, - "@webassemblyjs/ieee754": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.7.11.tgz", - "integrity": "sha1-yVg562N1ejGICq7HtlEtQZGsZAs=", + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha1-jWR0wbhwv9q807z8wZNKEOlPFfA=", "dev": true, "requires": { - "@xtuc/ieee754": "^1.2.0" + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" } }, - "@webassemblyjs/leb128": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.7.11.tgz", - "integrity": "sha1-1yZ6HunEWU/T9+NymIGOxlaH22M=", + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha1-OvTx9Zg5QDVy8cZiBDdfen9wPpw=", "dev": true, "requires": { - "@xtuc/long": "4.2.1" + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" } }, - "@webassemblyjs/utf8": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.7.11.tgz", - "integrity": "sha1-Btchjqn9yUpnk6qSIIFg2z0m7oI=", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.11.tgz", - "integrity": "sha1-jHTKR01PlR0B266b1wgU7iKoIAU=", + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-buffer": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/helper-wasm-section": "1.7.11", - "@webassemblyjs/wasm-gen": "1.7.11", - "@webassemblyjs/wasm-opt": "1.7.11", - "@webassemblyjs/wasm-parser": "1.7.11", - "@webassemblyjs/wast-printer": "1.7.11" + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" } }, - "@webassemblyjs/wasm-gen": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.11.tgz", - "integrity": "sha1-m7upQvIjdWhqb7dZr816ycRdoag=", + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/ieee754": "1.7.11", - "@webassemblyjs/leb128": "1.7.11", - "@webassemblyjs/utf8": "1.7.11" + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" } }, - "@webassemblyjs/wasm-opt": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.11.tgz", - "integrity": "sha1-szHo5874+OLwB9QsOjagWAp9bKc=", + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha1-KGlFnZqjviRf6P4sofRuLn9U1z8=", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-buffer": "1.7.11", - "@webassemblyjs/wasm-gen": "1.7.11", - "@webassemblyjs/wasm-parser": "1.7.11" + "pako": "~1.0.5" } }, - "@webassemblyjs/wasm-parser": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.11.tgz", - "integrity": "sha1-bj0g+mo1GfawhO+Tka1YIR77Cho=", + "browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-api-error": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/ieee754": "1.7.11", - "@webassemblyjs/leb128": "1.7.11", - "@webassemblyjs/utf8": "1.7.11" + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" } }, - "@webassemblyjs/wast-parser": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.7.11.tgz", - "integrity": "sha1-Jb0RdWLKjAAnIP+BFu+QctnKhpw=", + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/floating-point-hex-parser": "1.7.11", - "@webassemblyjs/helper-api-error": "1.7.11", - "@webassemblyjs/helper-code-frame": "1.7.11", - "@webassemblyjs/helper-fsm": "1.7.11", - "@xtuc/long": "4.2.1" + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" } }, - "@webassemblyjs/wast-printer": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.7.11.tgz", - "integrity": "sha1-xCRbbeJCy1CizJUBdP2/ZceNeBM=", + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha1-iQ3ZDZI6hz4I4Q5f1RpX5bfM4Ow=", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/wast-parser": "1.7.11", - "@xtuc/long": "4.2.1" + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" } }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha1-7vAUoxRa5Hehy8AM0eVSM23Ot5A=", + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha1-vX3CauKXLQ7aJTvgYdupkjScGfA=", "dev": true }, - "@xtuc/long": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.1.tgz", - "integrity": "sha1-XIXWYvdvodNFdXZsXc1mFavNMNg=", + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", "dev": true }, - "@zeit/schemas": { - "version": "2.36.0", - "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.36.0.tgz", - "integrity": "sha512-7kjMwcChYEzMKjeex9ZFXkt1AyNov9R5HZtjBKVsmVpw7pa7ZtlCGvCBC2vnnXctaYN+aRI61HjIqeetZW5ROg==", - "dev": true - }, - "7zip-bin": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-4.1.0.tgz", - "integrity": "sha1-M+/2YqXDnAwgYRcMwAPFEgdD//A=", + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", "dev": true }, - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha1-UxvHJlF6OytB+FACHGzBXqq1B80=", - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha1-MnE7wCj3XAL9txDXx7zsHyxgcO8=", + "dev": true }, - "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha1-Z6ojG/iBKXS4UjWpZ3Hra9B+onk=", + "buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha1-Uvq8xqYG0aADAoAmSO9o9jnaJow=", "dev": true }, - "acorn-dynamic-import": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz", - "integrity": "sha1-kBzu5Mf6rvfgetKkfokGddpQong=", - "dev": true, - "requires": { - "acorn": "^5.0.0" - } + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true }, - "acorn-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "builder-util": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-10.1.2.tgz", + "integrity": "sha1-KeYxAlqkyDdBHV5O9CXRTjIOstA=", "dev": true, - "optional": true, "requires": { - "acorn": "^3.0.4" + "@types/debug": "^4.1.4", + "7zip-bin": "~4.1.0", + "app-builder-bin": "2.7.1", + "bluebird-lst": "^1.0.9", + "builder-util-runtime": "^8.2.5", + "chalk": "^2.4.2", + "debug": "^4.1.1", + "fs-extra-p": "^8.0.2", + "is-ci": "^2.0.0", + "js-yaml": "^3.13.1", + "source-map-support": "^0.5.12", + "stat-mode": "^0.3.0", + "temp-file": "^3.3.3" }, "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha1-Z6npZL4xpR4V5QENWObxKDQAL0Y=", + "dev": true + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha1-a8YzQYGBDgS1wis9WJ/cpVAmQEw=", "dev": true, - "optional": true + "requires": { + "ci-info": "^2.0.0" + } } } }, - "acorn-walk": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", - "integrity": "sha1-Ejy487hMIXHx9/slJhWxx4prGow=", - "dev": true + "builder-util-runtime": { + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.2.5.tgz", + "integrity": "sha1-bxkzAXg0X4zixlhCsKnPahh9WUY=", + "dev": true, + "requires": { + "bluebird-lst": "^1.0.9", + "debug": "^4.1.1", + "fs-extra-p": "^8.0.2", + "sax": "^1.2.4" + } }, - "address": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/address/-/address-1.1.0.tgz", - "integrity": "sha1-744EeEf80sW29QwWll+ST9mf5wk=", + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", "dev": true }, - "after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha1-9s95M6Ng4FiPqf3oVlHNx/gF0fY=", + "dev": true }, - "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha1-086gTWsBeyiUrWkED+yLYj60vVI=", + "cacache": { + "version": "11.3.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.3.tgz", + "integrity": "sha1-i9Kd+ManGKbr0tAQ2k15cq47utw=", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" } }, - "ajv-errors": { + "cache-base": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha1-81mGrOuRr63sQQL72FAUlQzvpk0=", - "dev": true, - "requires": {} - }, - "ajv-keywords": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", - "integrity": "sha1-75FuJxxkrBIXH9g4TqrmsjRYVNo=", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", "dev": true, - "requires": {} - }, - "alphanum-sort": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", - "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", - "dev": true + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } }, - "ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "cache-loader": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cache-loader/-/cache-loader-2.0.1.tgz", + "integrity": "sha1-V1j0GmLXwjlB48PHAW5vrrA6ywc=", "dev": true, "requires": { - "string-width": "^4.1.0" + "loader-utils": "^1.1.0", + "mkdirp": "^0.5.1", + "neo-async": "^2.6.0", + "normalize-path": "^3.0.0", + "schema-utils": "^1.0.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", "dev": true, "requires": { - "ansi-regex": "^5.0.1" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } } } }, - "ansi-colors": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", - "integrity": "sha1-46PaS/uubIapwoViXeEkojQCb78=", - "dev": true - }, - "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha1-h4C5j/nb9WOBUtHx/lwde0RCl2s=", - "dev": true - }, - "ansi-html": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", - "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", - "dev": true - }, - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha1-i5+PCM8ay4Q3Vqg5yox+MWjFGZc=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", - "dev": true - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha1-vLJLTzeTTZqnrBe0ra+J58du8us=", + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha1-IP+4vRYrpL4R6VZ9gj22UQUsqRI=", "dev": true, "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" }, "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "get-stream": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", + "integrity": "sha1-ASA83JJZf5uQkGfD5lbMH008Tck=", "dev": true, "requires": { - "remove-trailing-separator": "^1.0.1" + "pump": "^3.0.0" } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha1-JgPni3tLAAbLyi+8yKMgJVislHk=", + "dev": true + }, + "normalize-url": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.3.0.tgz", + "integrity": "sha1-nEnhD8GHaut226iL8bK12fpXsu4=", + "dev": true } } }, - "app-builder-bin": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-2.7.1.tgz", - "integrity": "sha1-n2kK9lCTghuKYUmqKc6fjIH8VUw=", + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", "dev": true }, - "app-builder-lib": { - "version": "20.44.4", - "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-20.44.4.tgz", - "integrity": "sha1-OawgsxVeGwwkmYYrzeqHm1A4lXM=", + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", "dev": true, "requires": { - "7zip-bin": "~4.1.0", - "app-builder-bin": "2.7.1", - "async-exit-hook": "^2.0.1", - "bluebird-lst": "^1.0.9", - "builder-util": "10.1.2", - "builder-util-runtime": "8.2.5", - "chromium-pickle-js": "^0.2.0", - "debug": "^4.1.1", - "ejs": "^2.6.2", - "electron-osx-sign": "0.4.11", - "electron-publish": "20.44.4", - "fs-extra-p": "^8.0.2", - "hosted-git-info": "^2.7.1", - "is-ci": "^2.0.0", - "isbinaryfile": "^4.0.1", - "js-yaml": "^3.13.1", - "lazy-val": "^1.0.4", - "minimatch": "^3.0.4", - "normalize-package-data": "^2.5.0", - "plist": "^3.0.1", - "read-config-file": "3.2.2", - "sanitize-filename": "^1.6.1", - "semver": "^6.1.1", - "temp-file": "^3.3.3" + "callsites": "^2.0.0" }, "dependencies": { - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha1-Z6npZL4xpR4V5QENWObxKDQAL0Y=", - "dev": true - }, - "is-ci": { + "callsites": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha1-a8YzQYGBDgS1wis9WJ/cpVAmQEw=", - "dev": true, - "requires": { - "ci-info": "^2.0.0" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", "dev": true } } }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha1-aALmJk79GMeQobDVF/DyYnvyyUo=", - "dev": true + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "optional": true, + "requires": { + "callsites": "^0.2.0" + } }, - "arch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "dev": true + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" }, - "archiver": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", - "integrity": "sha1-/2YrSnggFJSj7lRNOjP+dJZQnrw=", + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true, + "optional": true + }, + "camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", "dev": true, "requires": { - "archiver-utils": "^1.3.0", - "async": "^2.0.0", - "buffer-crc32": "^0.2.1", - "glob": "^7.0.0", - "lodash": "^4.8.0", - "readable-stream": "^2.0.0", - "tar-stream": "^1.5.0", - "zip-stream": "^1.2.0" - }, - "dependencies": { - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha1-1yYl4jRKNlbjo61Pp0n6gymdgv8=", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - } + "no-case": "^2.2.0", + "upper-case": "^1.1.1" } }, - "archiver-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz", - "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=", + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha1-48mzFWnhBoEd8kL3FXJaH0xJQyA=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "dev": true, "requires": { - "glob": "^7.0.0", - "graceful-fs": "^4.1.0", - "lazystream": "^1.0.0", - "lodash": "^4.8.0", - "normalize-path": "^2.0.0", - "readable-stream": "^2.0.0" + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" }, "dependencies": { - "normalize-path": { + "camelcase": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true } } }, - "arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=", + "caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha1-Xk2Q4idJYdRikZl99Znj7QCO5MA=", "dev": true, "requires": { - "sprintf-js": "~1.0.2" + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" } }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "caniuse-lite": { + "version": "1.0.30001625", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001625.tgz", + "integrity": "sha512-4KE9N2gcRH+HQhpeiRZXd+1niLB/XNLAhSy4z7fI8EzcbcPoAqjNInxVHTiTwWfTIV4w096XG8OtCOCQQKPv3w==", "dev": true }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=", + "case-sensitive-paths-webpack-plugin": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.2.0.tgz", + "integrity": "sha1-M3HvY2XvnCX6S4HBas4OnH3FjD4=", "dev": true }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, - "array-filter": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", - "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", - "dev": true + "cbor-js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/cbor-js/-/cbor-js-0.1.0.tgz", + "integrity": "sha1-yAzmEg84fo+qdDcN/aIdlluPx/k=" }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ=", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "chalk-template": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", + "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", + "dev": true, + "requires": { + "chalk": "^4.1.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", "dev": true }, - "array-map": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", - "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", + "check-types": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/check-types/-/check-types-8.0.3.tgz", + "integrity": "sha1-M1bMoZyIlUTy16le1JzlCKDs9VI=", "dev": true }, - "array-reduce": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", - "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", + "chokidar": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz", + "integrity": "sha1-tsrWU6kp4kTOioNCRBZNJB+pVMU=", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "chownr": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz", + "integrity": "sha1-oY8eCyacimpdPIbrKYvrFMPde/Y=", "dev": true }, - "array-union": { + "chrome-trace-event": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha1-I0CQ7pfH1K0aLEvq4nUF3v/GCKQ=", "dev": true, "requires": { - "array-uniq": "^1.0.1" + "tslib": "^1.9.0" } }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "chromium-pickle-js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", + "integrity": "sha1-BKEGZywYsIWrd02YPfo+oTjyIgU=", "dev": true }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "ci-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", + "integrity": "sha1-LKINu5zrMtRSSmgzAzE/AwSx5Jc=", "dev": true }, - "arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" - }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha1-jSR136tVO7M+d7VOWeiAu4ziMTY=", + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94=", "dev": true, "requires": { - "safer-buffer": "~2.1.0" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, - "asn1.js": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha1-ucK/WAXx5kqt7tbfOiv6+1pz9aA=", + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha1-gVyZ6oT2gJUp0vRXkb34JxE1LWY=", "dev": true, - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } + "optional": true }, - "assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha1-VcEJqvbgrv2z3EtxJAxwv1dLGOs=", + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", "dev": true, "requires": { - "object-assign": "^4.1.1", - "util": "0.10.3" + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" }, "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "inherits": "2.0.1" + "is-descriptor": "^0.1.0" } } } }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha1-bIw/uCfdQ+45GPJ7gngqt2WKb9k=", - "dev": true + "clean-css": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", + "integrity": "sha1-LUEe92uFabbQyEBo2r6FsKpeXBc=", + "dev": true, + "requires": { + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + } + } }, - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "cli-boxes": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz", + "integrity": "sha1-U47K6PnGylCOPDyVtFP+k8tMFo0=", "dev": true }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha1-tyfb+H12UWAvBvTUrDh/R9kbDL8=", - "dev": true + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } }, - "async-exit-hook": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", - "integrity": "sha1-i9iwJLDsmxwBzMua+dspvXF9+vM=", - "dev": true - }, - "async-limiter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha1-ePrtjD0HSrgfIrTphdeehzj3IPg=" - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha1-bZUX654DDSQ2ZmZR6GvZ9vE1M8k=", - "dev": true - }, - "autoprefixer": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.6.1.tgz", - "integrity": "sha1-UZZ6AtLSMAuwGGbBYR7INI01Wkc=", + "cli-highlight": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.1.tgz", + "integrity": "sha1-IYAiPVFhixEvRQnPluSmx1Cwfpc=", "dev": true, "requires": { - "browserslist": "^4.6.3", - "caniuse-lite": "^1.0.30000980", - "chalk": "^2.4.2", - "normalize-range": "^0.1.2", - "num2fraction": "^1.2.2", - "postcss": "^7.0.17", - "postcss-value-parser": "^4.0.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.0.tgz", - "integrity": "sha1-mamD02X3sq2ND5uMMJSSbqtLk20=", - "dev": true - } + "chalk": "^2.3.0", + "highlight.js": "^9.6.0", + "mz": "^2.4.0", + "parse5": "^4.0.0", + "yargs": "^13.0.0" } }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "cli-spinners": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.2.0.tgz", + "integrity": "sha1-6LmI2SBsaSMC2O6DTnqFwBRNj3c=", "dev": true }, - "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha1-8OAD2cqef1nHpQiUXXsu+aBKVC8=", + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", "dev": true }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "clipboardy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.1.0.tgz", + "integrity": "sha1-ASOgyPrJLyVtxWM14LuL6XpJCaU=", "dev": true, "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } + "arch": "^2.1.1", + "execa": "^1.0.0" } }, - "babel-eslint": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.2.tgz", - "integrity": "sha1-GC1awgRXn/CIFoSwQFYP3MFVhFY=", + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha1-3u/P2y6AB4SqNPRvoI4GhRx7u8U=", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.0.0", - "@babel/traverse": "^7.0.0", - "@babel/types": "^7.0.0", - "eslint-scope": "3.7.1", - "eslint-visitor-keys": "^1.0.0" + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" }, "dependencies": { - "eslint-scope": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", - "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha1-InZ74htirxCBV0MG9prFG2IgOWE=", "dev": true, "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" } } } }, - "babel-loader": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.6.tgz", - "integrity": "sha1-4zvbbzYrA/S7FBoMIauHxQG3Dfs=", + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", "dev": true, "requires": { - "find-cache-dir": "^2.0.0", - "loader-utils": "^1.0.2", - "mkdirp": "^0.5.1", - "pify": "^4.0.1" + "mimic-response": "^1.0.0" } }, - "babel-plugin-dynamic-import-node": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", - "integrity": "sha1-8A9Qe9qjw+P/bn5emNkKesq5b38=", + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true, + "optional": true + }, + "coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha1-Q/bCEVG07yv1cYfbDXPeIp4+fsM=", "dev": true, "requires": { - "object.assign": "^4.1.0" + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" } }, - "babel-plugin-module-resolver": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-3.2.0.tgz", - "integrity": "sha1-3fpeMB47mqEthSqZefGLN4gf9ac=", + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, "requires": { - "find-babel-config": "^1.1.0", - "glob": "^7.1.2", - "pkg-up": "^2.0.0", - "reselect": "^3.0.1", - "resolve": "^1.4.0" + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" } }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/color/-/color-3.1.2.tgz", + "integrity": "sha1-aBSOf4XUGtdknF+oyBBvCY0inhA=", "dev": true, "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha1-vgWtf5v30i4Fb5cmzuUBf78Z4uk=", - "dev": true - } + "color-convert": "^1.9.1", + "color-string": "^1.5.2" } }, - "backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg=", + "dev": true, + "requires": { + "color-name": "1.1.3" + } }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", + "color-string": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", + "integrity": "sha1-ybvF8BtYtUkvPWhXRZy2WQziBMw=", "dev": true, "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" } }, - "base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" - }, - "base64-js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha1-yrHmEY8FEJXli1KBrqjBzSK/wOM=", - "dev": true - }, - "base64id": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", - "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=" - }, - "batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha1-w9RaizT9cwYxoRCoolIGgrMdWn8=", "dev": true, "requires": { - "tweetnacl": "^0.14.3" + "delayed-stream": "~1.0.0" } }, - "better-assert": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", - "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "requires": { - "callsite": "1.0.0" - } + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha1-1YuytcHuj4ew00ACfp6U4iLFpCI=", + "dev": true }, - "bfj": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.2.tgz", - "integrity": "sha1-MlyGGoIryzWKQceKM7jm4ght3n8=", - "dev": true, - "requires": { - "bluebird": "^3.5.5", - "check-types": "^8.0.3", - "hoopy": "^0.1.4", - "tryer": "^1.0.1" - } + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha1-ZfCvOC9Xi83HQr2cKB6cstd2gyg=", + "compare-version": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", + "integrity": "sha1-AWLsLZNR9d3VmpICy6k1NmpyUIA=", "dev": true }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha1-WYr+VHVbKGilMw0q/51Ou1Mgm2U=", + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha1-FuQHD7qK4ptnnyIVhT7hgasuq8A=", "dev": true }, - "bl": { + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" + }, + "compress-commons": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", - "integrity": "sha1-oWCRFxcQPAdBDO9j71Gzl8Alr5w=", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", + "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", "dev": true, "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" + "buffer-crc32": "^0.2.1", + "crc32-stream": "^2.0.0", + "normalize-path": "^2.0.0", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } } }, - "blob": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", - "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" - }, - "bluebird": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz", - "integrity": "sha1-qNCv1zJR7/u9X+OEp31zADwXpx8=", - "dev": true - }, - "bluebird-lst": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz", - "integrity": "sha1-pkoOQ2Vli5q1/odeud+2lBibtBw=", + "compressible": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.17.tgz", + "integrity": "sha1-bowQihatWDhKl386SCyiC/8vOME=", "dev": true, "requires": { - "bluebird": "^3.5.5" + "mime-db": ">= 1.40.0 < 2" } }, - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha1-LN4J617jQfSEdGuwMJsyU7GxRC8=", - "dev": true - }, - "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha1-lrJwnlfJxOCab9Zqj9l5hE9p8Io=", + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha1-lVI+/xcMpXwpoMpB5v4TH0Hlu48=", "dev": true, "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" }, "dependencies": { + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -19948,2267 +20300,2090 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha1-QdwaAV49WB8WIXdr4xr7KHapsbw=", - "dev": true } } }, - "bonjour": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", - "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha1-kEvfGUzTEi/Gdcd/xKw9T/D9GjQ=", "dev": true, "requires": { - "array-flatten": "^2.1.0", - "deep-equal": "^1.0.1", - "dns-equal": "^1.0.0", - "dns-txt": "^2.0.2", - "multicast-dns": "^6.0.1", - "multicast-dns-service-types": "^1.1.0" - }, - "dependencies": { - "array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha1-JO+AoowaiTYX4hSbDG0NeIKTsJk=", - "dev": true - } + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" } }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "boxen": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-3.2.0.tgz", - "integrity": "sha1-+9/w3pNjarRFCIa2/0W5LQmPRes=", + "configstore": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-4.0.0.tgz", + "integrity": "sha1-WTMxHpXTaH77WSxSi5ItkmLSJ+c=", "dev": true, "requires": { - "ansi-align": "^3.0.0", - "camelcase": "^5.3.1", - "chalk": "^2.4.2", - "cli-boxes": "^2.2.0", - "string-width": "^3.0.0", - "term-size": "^1.2.0", - "type-fest": "^0.3.0", - "widest-line": "^2.0.0" + "dot-prop": "^4.1.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "unique-string": "^1.0.0", + "write-file-atomic": "^2.0.0", + "xdg-basedir": "^3.0.0" }, "dependencies": { - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha1-InZ74htirxCBV0MG9prFG2IgOWE=", + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha1-ecEDO4BRW9bSTsmTPoYMp17ifww=", "dev": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "pify": "^3.0.0" } }, - "type-fest": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", - "integrity": "sha1-Y9ANIE4FlHT+Xht8ARESu9HcKeE=", + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true } } }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha1-izIIk1kwjRERFdgcrT/Oq4iPl7w=", "dev": true }, - "browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha1-Mmc0ZC9APavDADIJhTu3CtQo70g=", + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", "dev": true, "requires": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "date-now": "^0.1.4" } }, - "browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha1-jWR0wbhwv9q807z8wZNKEOlPFfA=", + "consolidate": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz", + "integrity": "sha1-IasEMjXHGgfUXZqtmFk7DbpWurc=", "dev": true, "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" + "bluebird": "^3.1.1" } }, - "browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha1-OvTx9Zg5QDVy8cZiBDdfen9wPpw=", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true }, - "browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha1-4TDK9+cnkIfFYWwgB9BIVpiYT70=", "dev": true, "requires": { - "bn.js": "^4.1.0", - "randombytes": "^2.0.1" + "safe-buffer": "5.1.2" } }, - "browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true, - "requires": { - "bn.js": "^4.1.1", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.2", - "elliptic": "^6.0.0", - "inherits": "^2.0.1", - "parse-asn1": "^5.0.0" - } + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=", + "dev": true }, - "browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha1-KGlFnZqjviRf6P4sofRuLn9U1z8=", + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha1-UbU3qMQ+DwTewZk7/83VBOdYrCA=", "dev": true, "requires": { - "pako": "~1.0.5" + "safe-buffer": "~5.1.1" } }, - "browserslist": { - "version": "4.6.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.6.tgz", - "integrity": "sha1-bkv0Z83lILydvfN0fa+gNTHOxFM=", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000984", - "electron-to-chromium": "^1.3.191", - "node-releases": "^1.1.25" - } + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha1-vrQ35wIrO21JAZ0IhmUwPr6cFLo=", + "dev": true }, - "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true }, - "buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha1-iQ3ZDZI6hz4I4Q5f1RpX5bfM4Ow=", + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha1-kilzmMrjSTf8r9bsgTnBgFHwteA=", "dev": true, "requires": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" } }, - "buffer-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha1-vX3CauKXLQ7aJTvgYdupkjScGfA=", - "dev": true - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true - }, - "buffer-fill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", - "dev": true - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha1-MnE7wCj3XAL9txDXx7zsHyxgcO8=", - "dev": true - }, - "buffer-indexof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", - "integrity": "sha1-Uvq8xqYG0aADAoAmSO9o9jnaJow=", + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true - }, - "builder-util": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-10.1.2.tgz", - "integrity": "sha1-KeYxAlqkyDdBHV5O9CXRTjIOstA=", + "copy-webpack-plugin": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.6.0.tgz", + "integrity": "sha1-5/QN2KaEd9QF3Rt6hUquMksVi64=", "dev": true, "requires": { - "@types/debug": "^4.1.4", - "7zip-bin": "~4.1.0", - "app-builder-bin": "2.7.1", - "bluebird-lst": "^1.0.9", - "builder-util-runtime": "^8.2.5", - "chalk": "^2.4.2", - "debug": "^4.1.1", - "fs-extra-p": "^8.0.2", - "is-ci": "^2.0.0", - "js-yaml": "^3.13.1", - "source-map-support": "^0.5.12", - "stat-mode": "^0.3.0", - "temp-file": "^3.3.3" + "cacache": "^10.0.4", + "find-cache-dir": "^1.0.0", + "globby": "^7.1.1", + "is-glob": "^4.0.0", + "loader-utils": "^1.1.0", + "minimatch": "^3.0.4", + "p-limit": "^1.0.0", + "serialize-javascript": "^1.4.0" }, "dependencies": { - "ci-info": { + "cacache": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", + "integrity": "sha1-ZFI2eZnv+dQYiu/ZoU6dfGomNGA=", + "dev": true, + "requires": { + "bluebird": "^3.5.1", + "chownr": "^1.0.1", + "glob": "^7.1.2", + "graceful-fs": "^4.1.11", + "lru-cache": "^4.1.1", + "mississippi": "^2.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.2", + "ssri": "^5.2.4", + "unique-filename": "^1.1.0", + "y18n": "^4.0.0" + } + }, + "find-cache-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^2.0.0" + } + }, + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "dir-glob": "^2.0.0", + "glob": "^7.1.2", + "ignore": "^3.3.5", + "pify": "^3.0.0", + "slash": "^1.0.0" + } + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha1-ecEDO4BRW9bSTsmTPoYMp17ifww=", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "mississippi": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha1-Z6npZL4xpR4V5QENWObxKDQAL0Y=", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", + "integrity": "sha1-NEKlCPr8KFAEhv7qmUCWduTuWm8=", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^2.0.1", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true }, - "is-ci": { + "pkg-dir": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha1-a8YzQYGBDgS1wis9WJ/cpVAmQEw=", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", "dev": true, "requires": { - "ci-info": "^2.0.0" + "find-up": "^2.1.0" + } + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha1-Ejma3W5M91Jtlzy8i1zi4pCLOQk=", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "ssri": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", + "integrity": "sha1-ujhyycbTOgcEp9cf8EXl7EiZnQY=", + "dev": true, + "requires": { + "safe-buffer": "^5.1.1" } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true } } }, - "builder-util-runtime": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.2.5.tgz", - "integrity": "sha1-bxkzAXg0X4zixlhCsKnPahh9WUY=", - "dev": true, - "requires": { - "bluebird-lst": "^1.0.9", - "debug": "^4.1.1", - "fs-extra-p": "^8.0.2", - "sax": "^1.2.4" - } - }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", - "dev": true + "core-js": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", + "integrity": "sha1-a0shRiDINBUuF5Mjcn/Bl0GwhPI=" }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha1-9s95M6Ng4FiPqf3oVlHNx/gF0fY=", + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, - "cacache": { - "version": "11.3.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.3.tgz", - "integrity": "sha1-i9Kd+ManGKbr0tAQ2k15cq47utw=", - "dev": true, - "requires": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", - "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" - } - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha1-BA9yaAnFked6F8CjYmykW08Wixo=", "dev": true, "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" } }, - "cache-loader": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/cache-loader/-/cache-loader-2.0.1.tgz", - "integrity": "sha1-V1j0GmLXwjlB48PHAW5vrrA6ywc=", + "crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha1-rWAmnCyFb4wpnixMwN5FVpFAVsY=", "dev": true, "requires": { - "loader-utils": "^1.1.0", - "mkdirp": "^0.5.1", - "neo-async": "^2.6.0", - "normalize-path": "^3.0.0", - "schema-utils": "^1.0.0" + "buffer": "^5.1.0" }, "dependencies": { - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", + "buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha1-3Vf6DxCaxZxgJHkETcp7iz0LcdY=", "dev": true, "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" } } } }, - "cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha1-IP+4vRYrpL4R6VZ9gj22UQUsqRI=", + "crc32-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", + "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", "dev": true, "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "dependencies": { - "get-stream": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", - "integrity": "sha1-ASA83JJZf5uQkGfD5lbMH008Tck=", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha1-JgPni3tLAAbLyi+8yKMgJVislHk=", - "dev": true - }, - "normalize-url": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.3.0.tgz", - "integrity": "sha1-nEnhD8GHaut226iL8bK12fpXsu4=", - "dev": true - } + "crc": "^3.4.4", + "readable-stream": "^2.0.0" } }, - "call-me-maybe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", - "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", - "dev": true - }, - "caller-callsite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", - "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha1-yREbbzMEXEaX8UR4f5JUzcd8Rf8=", "dev": true, "requires": { - "callsites": "^2.0.0" - }, - "dependencies": { - "callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", - "dev": true - } + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" } }, - "caller-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha1-iJB4rxGmN1a8+1m9IhmWvjqe8ZY=", "dev": true, - "optional": true, "requires": { - "callsites": "^0.2.0" + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" } }, - "callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha1-aRcMeLOrlXFHsriwRXLkfq0iQ/8=", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } }, - "callsites": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha1-Sl7Hxk364iw6FBJNus3uhG2Ay8Q=", "dev": true, - "optional": true + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } }, - "camel-case": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", - "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha1-OWz58xN/A+S45TLFj2mCVOAPgOw=", "dev": true, "requires": { - "no-case": "^2.2.0", - "upper-case": "^1.1.1" + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" } }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha1-48mzFWnhBoEd8kL3FXJaH0xJQyA=", + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", "dev": true }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "css": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", + "integrity": "sha1-xkZ1XHOXHyu6amAeLPL9cbEpiSk=", "dev": true, "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.0" }, "dependencies": { - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true } } }, - "caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha1-Xk2Q4idJYdRikZl99Znj7QCO5MA=", - "dev": true, - "requires": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, - "caniuse-lite": { - "version": "1.0.30000985", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000985.tgz", - "integrity": "sha1-DrQPbIqMIZFVy+Q8SXXA77Sg938=", - "dev": true - }, - "case-sensitive-paths-webpack-plugin": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.2.0.tgz", - "integrity": "sha1-M3HvY2XvnCX6S4HBas4OnH3FjD4=", - "dev": true - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", "dev": true }, - "cbor-js": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/cbor-js/-/cbor-js-0.1.0.tgz", - "integrity": "sha1-yAzmEg84fo+qdDcN/aIdlluPx/k=" - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ=", + "css-declaration-sorter": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz", + "integrity": "sha1-wZiUD2OnbX42wecQGLABchBUyyI=", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "postcss": "^7.0.1", + "timsort": "^0.3.0" } }, - "chalk-template": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", - "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", + "css-loader": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-1.0.1.tgz", + "integrity": "sha1-aIW7UjOzXsR7AGBX2gHMZAtref4=", "dev": true, "requires": { - "chalk": "^4.1.2" + "babel-code-frame": "^6.26.0", + "css-selector-tokenizer": "^0.7.0", + "icss-utils": "^2.1.0", + "loader-utils": "^1.0.2", + "lodash": "^4.17.11", + "postcss": "^6.0.23", + "postcss-modules-extract-imports": "^1.2.0", + "postcss-modules-local-by-default": "^1.2.0", + "postcss-modules-scope": "^1.1.0", + "postcss-modules-values": "^1.3.0", + "postcss-value-parser": "^3.3.0", + "source-list-map": "^2.0.0" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha1-YcgswyisYOZ3ZF+XkFTrmLwOMyQ=", "dev": true, "requires": { - "color-convert": "^2.0.1" + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" } }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } } } }, - "chardet": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", - "dev": true - }, - "check-types": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/check-types/-/check-types-8.0.3.tgz", - "integrity": "sha1-M1bMoZyIlUTy16le1JzlCKDs9VI=", - "dev": true - }, - "chokidar": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz", - "integrity": "sha1-tsrWU6kp4kTOioNCRBZNJB+pVMU=", + "css-parse": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", + "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", "dev": true, "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" + "css": "^2.0.0" } }, - "chownr": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz", - "integrity": "sha1-oY8eCyacimpdPIbrKYvrFMPde/Y=", - "dev": true - }, - "chrome-trace-event": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha1-I0CQ7pfH1K0aLEvq4nUF3v/GCKQ=", + "css-select": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.0.2.tgz", + "integrity": "sha1-q0OGzsnh9miFVWSxfDcztDsqXt4=", "dev": true, "requires": { - "tslib": "^1.9.0" + "boolbase": "^1.0.0", + "css-what": "^2.1.2", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" } }, - "chromium-pickle-js": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", - "integrity": "sha1-BKEGZywYsIWrd02YPfo+oTjyIgU=", - "dev": true - }, - "ci-info": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", - "integrity": "sha1-LKINu5zrMtRSSmgzAzE/AwSx5Jc=", + "css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha1-Oy/0lyzDYquIVhUHqVQIoUMhNdc=", "dev": true }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "circular-json": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha1-gVyZ6oT2gJUp0vRXkb34JxE1LWY=", - "dev": true, - "optional": true - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", + "css-selector-tokenizer": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz", + "integrity": "sha1-oXcnGovKUBkXL0+JH8bu2cv2jV0=", "dev": true, "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" + "cssesc": "^0.1.0", + "fastparse": "^1.1.1", + "regexpu-core": "^1.0.0" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "cssesc": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", + "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=", + "dev": true + }, + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + }, + "regexpu-core": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", + "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "~0.5.0" } } } }, - "clean-css": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", - "integrity": "sha1-LUEe92uFabbQyEBo2r6FsKpeXBc=", + "css-tree": { + "version": "1.0.0-alpha.33", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.33.tgz", + "integrity": "sha1-lw4g5akfejeN3Q/FjQtsjU876T4=", "dev": true, "requires": { - "source-map": "~0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", - "dev": true - } + "mdn-data": "2.0.4", + "source-map": "^0.5.3" } }, - "cli-boxes": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz", - "integrity": "sha1-U47K6PnGylCOPDyVtFP+k8tMFo0=", + "css-unit-converter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.1.tgz", + "integrity": "sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY=", "dev": true }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "requires": { - "restore-cursor": "^2.0.0" - } - }, - "cli-highlight": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.1.tgz", - "integrity": "sha1-IYAiPVFhixEvRQnPluSmx1Cwfpc=", - "dev": true, - "requires": { - "chalk": "^2.3.0", - "highlight.js": "^9.6.0", - "mz": "^2.4.0", - "parse5": "^4.0.0", - "yargs": "^13.0.0" - } + "css-value": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/css-value/-/css-value-0.0.1.tgz", + "integrity": "sha1-Xv1sLupeof1rasV+wEJ7GEUkJOo=", + "dev": true }, - "cli-spinners": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.2.0.tgz", - "integrity": "sha1-6LmI2SBsaSMC2O6DTnqFwBRNj3c=", + "css-what": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha1-ptdgRXM2X+dGhsPzEcVlE9iChfI=", "dev": true }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha1-OxO9G7HLNuG8taTc0n9UxdyzVwM=", "dev": true }, - "clipboardy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.1.0.tgz", - "integrity": "sha1-ASOgyPrJLyVtxWM14LuL6XpJCaU=", + "cssnano": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz", + "integrity": "sha1-CsQfCxPRPUZUh+ERt3jULaYxuLI=", "dev": true, "requires": { - "arch": "^2.1.1", - "execa": "^1.0.0" + "cosmiconfig": "^5.0.0", + "cssnano-preset-default": "^4.0.7", + "is-resolvable": "^1.0.0", + "postcss": "^7.0.0" } }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha1-3u/P2y6AB4SqNPRvoI4GhRx7u8U=", + "cssnano-preset-default": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz", + "integrity": "sha1-UexmLM/KD4izltzZZ5zbkxvhf3Y=", "dev": true, "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - }, - "dependencies": { - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha1-InZ74htirxCBV0MG9prFG2IgOWE=", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - } + "css-declaration-sorter": "^4.0.1", + "cssnano-util-raw-cache": "^4.0.1", + "postcss": "^7.0.0", + "postcss-calc": "^7.0.1", + "postcss-colormin": "^4.0.3", + "postcss-convert-values": "^4.0.1", + "postcss-discard-comments": "^4.0.2", + "postcss-discard-duplicates": "^4.0.2", + "postcss-discard-empty": "^4.0.1", + "postcss-discard-overridden": "^4.0.1", + "postcss-merge-longhand": "^4.0.11", + "postcss-merge-rules": "^4.0.3", + "postcss-minify-font-values": "^4.0.2", + "postcss-minify-gradients": "^4.0.2", + "postcss-minify-params": "^4.0.2", + "postcss-minify-selectors": "^4.0.2", + "postcss-normalize-charset": "^4.0.1", + "postcss-normalize-display-values": "^4.0.2", + "postcss-normalize-positions": "^4.0.2", + "postcss-normalize-repeat-style": "^4.0.2", + "postcss-normalize-string": "^4.0.2", + "postcss-normalize-timing-functions": "^4.0.2", + "postcss-normalize-unicode": "^4.0.1", + "postcss-normalize-url": "^4.0.1", + "postcss-normalize-whitespace": "^4.0.2", + "postcss-ordered-values": "^4.1.2", + "postcss-reduce-initial": "^4.0.3", + "postcss-reduce-transforms": "^4.0.2", + "postcss-svgo": "^4.0.2", + "postcss-unique-selectors": "^4.0.1" } }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "cssnano-util-get-arguments": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz", + "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=", "dev": true }, - "clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "cssnano-util-get-match": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz", + "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=", + "dev": true + }, + "cssnano-util-raw-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz", + "integrity": "sha1-sm1f1fcqEd/np4RvtMZyYPlr8oI=", "dev": true, "requires": { - "mimic-response": "^1.0.0" + "postcss": "^7.0.0" } }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true, - "optional": true + "cssnano-util-same-parent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz", + "integrity": "sha1-V0CC+yhZ0ttDOFWDXZqEVuoYu/M=", + "dev": true }, - "coa": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", - "integrity": "sha1-Q/bCEVG07yv1cYfbDXPeIp4+fsM=", + "csso": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/csso/-/csso-3.5.1.tgz", + "integrity": "sha1-e564vmFiiXPBsmHhadLwJACOdYs=", "dev": true, "requires": { - "@types/q": "^1.5.1", - "chalk": "^2.4.1", - "q": "^1.1.2" + "css-tree": "1.0.0-alpha.29" + }, + "dependencies": { + "css-tree": { + "version": "1.0.0-alpha.29", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.29.tgz", + "integrity": "sha1-P6nU7zFCy9HDAedmTB81K9gvWjk=", + "dev": true, + "requires": { + "mdn-data": "~1.1.0", + "source-map": "^0.5.3" + } + }, + "mdn-data": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-1.1.4.tgz", + "integrity": "sha1-ULXU/8RXUnZXPE7tuHgIEqhBnwE=", + "dev": true + } } }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "current-script-polyfill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/current-script-polyfill/-/current-script-polyfill-1.0.0.tgz", + "integrity": "sha1-8xz35PPiGLBybnOMqSoC00iO9hU=", "dev": true }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", "dev": true, "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" + "array-find-index": "^1.0.1" } }, - "color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/color/-/color-3.1.2.tgz", - "integrity": "sha1-aBSOf4XUGtdknF+oyBBvCY0inhA=", - "dev": true, - "requires": { - "color-convert": "^1.9.1", - "color-string": "^1.5.2" - } + "cyclist": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", + "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", + "dev": true }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg=", + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, "requires": { - "color-name": "1.1.3" + "assert-plus": "^1.0.0" } }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", "dev": true }, - "color-string": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", - "integrity": "sha1-ybvF8BtYtUkvPWhXRZy2WQziBMw=", - "dev": true, + "de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=", "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" + "ms": "^2.1.1" } }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha1-w9RaizT9cwYxoRCoolIGgrMdWn8=", + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", "dev": true, "requires": { - "delayed-stream": "~1.0.0" + "mimic-response": "^1.0.0" } }, - "commander": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha1-1YuytcHuj4ew00ACfp6U4iLFpCI=", - "dev": true - }, - "commondir": { + "deep-equal": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", "dev": true }, - "compare-version": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", - "integrity": "sha1-AWLsLZNR9d3VmpICy6k1NmpyUIA=", + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha1-xPp8lUBKF6nD6Mp+FTcxK3NjMKw=", "dev": true }, - "component-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", - "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha1-FuQHD7qK4ptnnyIVhT7hgasuq8A=", + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, - "component-inherit": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", - "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" + "deepmerge": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz", + "integrity": "sha1-EEmdhohEza1P7ghC34x/bwyVp1M=", + "dev": true }, - "compress-commons": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", - "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", - "dev": true, - "requires": { - "buffer-crc32": "^0.2.1", - "crc32-stream": "^2.0.0", - "normalize-path": "^2.0.0", - "readable-stream": "^2.0.0" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "compressible": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.17.tgz", - "integrity": "sha1-bowQihatWDhKl386SCyiC/8vOME=", + "default-gateway": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-5.0.2.tgz", + "integrity": "sha1-0tihPW/uQG2TZdGeya3MuKYLgrM=", "dev": true, "requires": { - "mime-db": ">= 1.40.0 < 2" + "execa": "^1.0.0", + "ip-regex": "^2.1.0" } }, - "compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha1-lVI+/xcMpXwpoMpB5v4TH0Hlu48=", + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", "dev": true, "requires": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "dependencies": { - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } + "clone": "^1.0.2" } }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "defer-to-connect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.0.2.tgz", + "integrity": "sha1-S651ijFLA0rjOQK1qsJajdaoYz4=", "dev": true }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha1-kEvfGUzTEi/Gdcd/xKw9T/D9GjQ=", + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE=", "dev": true, "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" + "object-keys": "^1.0.12" } }, - "configstore": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-4.0.0.tgz", - "integrity": "sha1-WTMxHpXTaH77WSxSi5ItkmLSJ+c=", + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=", "dev": true, "requires": { - "dot-prop": "^4.1.0", - "graceful-fs": "^4.1.2", - "make-dir": "^1.0.0", - "unique-string": "^1.0.0", - "write-file-atomic": "^2.0.0", - "xdg-basedir": "^3.0.0" + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" }, "dependencies": { - "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha1-ecEDO4BRW9bSTsmTPoYMp17ifww=", + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { - "pify": "^3.0.0" + "kind-of": "^6.0.0" } }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } } } }, - "connect-history-api-fallback": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", - "integrity": "sha1-izIIk1kwjRERFdgcrT/Oq4iPl7w=", - "dev": true - }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true, - "requires": { - "date-now": "^0.1.4" - } - }, - "consolidate": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz", - "integrity": "sha1-IasEMjXHGgfUXZqtmFk7DbpWurc=", + "del": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha1-no8RciLqRKMf86FWwEm5kFKp8LQ=", "dev": true, "requires": { - "bluebird": "^3.1.1" + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "dependencies": { + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + } } }, - "constants-browserify": { + "delayed-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, - "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha1-4TDK9+cnkIfFYWwgB9BIVpiYT70=", + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", "dev": true, "requires": { - "safe-buffer": "5.1.2" + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" } }, - "content-type": { + "destroy": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", "dev": true }, - "convert-source-map": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha1-UbU3qMQ+DwTewZk7/83VBOdYrCA=", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha1-vrQ35wIrO21JAZ0IhmUwPr6cFLo=", + "detect-node": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", + "integrity": "sha1-AU7o+PZpxcWAI9pkuBecCDooxGw=", "dev": true }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev-null": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dev-null/-/dev-null-0.1.1.tgz", + "integrity": "sha1-WiBc48Ky73e2I41roXnrdMag6Bg=", "dev": true }, - "copy-concurrently": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha1-kilzmMrjSTf8r9bsgTnBgFHwteA=", + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha1-QOjumPVaIUlgcUaSHGPhrl89KHU=", "dev": true, "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" } }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "copy-webpack-plugin": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.6.0.tgz", - "integrity": "sha1-5/QN2KaEd9QF3Rt6hUquMksVi64=", + "dir-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha1-+gnwaUFTyJGLGLoN6vrpR2n8UMQ=", "dev": true, "requires": { - "cacache": "^10.0.4", - "find-cache-dir": "^1.0.0", - "globby": "^7.1.1", - "is-glob": "^4.0.0", - "loader-utils": "^1.1.0", - "minimatch": "^3.0.4", - "p-limit": "^1.0.0", - "serialize-javascript": "^1.4.0" - }, - "dependencies": { - "cacache": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", - "integrity": "sha1-ZFI2eZnv+dQYiu/ZoU6dfGomNGA=", - "dev": true, - "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.1", - "mississippi": "^2.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.2", - "ssri": "^5.2.4", - "unique-filename": "^1.1.0", - "y18n": "^4.0.0" - } - }, - "find-cache-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", - "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^1.0.0", - "pkg-dir": "^2.0.0" - } - }, - "globby": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", - "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "dir-glob": "^2.0.0", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" - } - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha1-ecEDO4BRW9bSTsmTPoYMp17ifww=", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "mississippi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", - "integrity": "sha1-NEKlCPr8KFAEhv7qmUCWduTuWm8=", - "dev": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^2.0.1", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - } - }, - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha1-Ejma3W5M91Jtlzy8i1zi4pCLOQk=", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true - }, - "ssri": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", - "integrity": "sha1-ujhyycbTOgcEp9cf8EXl7EiZnQY=", - "dev": true, - "requires": { - "safe-buffer": "^5.1.1" - } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - } + "path-type": "^3.0.0" } }, - "core-js": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", - "integrity": "sha1-a0shRiDINBUuF5Mjcn/Bl0GwhPI=" - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "cosmiconfig": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", - "integrity": "sha1-BA9yaAnFked6F8CjYmykW08Wixo=", + "dmg-builder": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-6.7.2.tgz", + "integrity": "sha1-S6SVXn818VnOU8aNdNPqdIdfmv0=", "dev": true, "requires": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", + "app-builder-lib": "~20.44.4", + "bluebird-lst": "^1.0.9", + "builder-util": "~10.1.2", + "fs-extra-p": "^8.0.2", + "iconv-lite": "^0.4.24", "js-yaml": "^3.13.1", - "parse-json": "^4.0.0" + "parse-color": "^1.0.0", + "sanitize-filename": "^1.6.1" } }, - "crc": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", - "integrity": "sha1-rWAmnCyFb4wpnixMwN5FVpFAVsY=", + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", + "dev": true + }, + "dns-packet": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", + "integrity": "sha1-EqpCaYEHW+UAuRDu3NC0fdfe2lo=", "dev": true, "requires": { - "buffer": "^5.1.0" - }, - "dependencies": { - "buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", - "integrity": "sha1-3Vf6DxCaxZxgJHkETcp7iz0LcdY=", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - } + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" } }, - "crc32-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", - "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", + "dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", "dev": true, "requires": { - "crc": "^3.4.4", - "readable-stream": "^2.0.0" + "buffer-indexof": "^1.0.0" } }, - "create-ecdh": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", - "integrity": "sha1-yREbbzMEXEaX8UR4f5JUzcd8Rf8=", + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha1-XNAfwQFiG0LEzX9dGmYkNxbT850=", "dev": true, + "optional": true, "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.0.0" + "esutils": "^2.0.2" } }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha1-iJB4rxGmN1a8+1m9IhmWvjqe8ZY=", + "dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha1-ZyGp2u4uKTaClVtq/kFncWJ7t2g=", "dev": true, "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" + "utila": "~0.4" } }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha1-aRcMeLOrlXFHsriwRXLkfq0iQ/8=", + "dom-serializer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha1-HsQFnihLq+027sKUHUqXChic58A=", "dev": true, "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" + "domelementtype": "^1.3.0", + "entities": "^1.1.1" } }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha1-Sl7Hxk364iw6FBJNus3uhG2Ay8Q=", + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha1-PTH1AZGmdJ3RN1p/Ui6CPULlTto=", + "dev": true + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha1-0EjESzew0Qp/Kj1f7j9DM9eQSB8=", + "dev": true + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha1-iAUJfpM9ZehVRvcm1g9euItE+AM=", "dev": true, "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "domelementtype": "1" } }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha1-OWz58xN/A+S45TLFj2mCVOAPgOw=", + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha1-Vuo0HoNOBuZ0ivehyyXaZ+qfjCo=", "dev": true, "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha1-HxngwuGqDjJ5fEl5nyg3rGr2nFc=", + "dev": true, + "requires": { + "is-obj": "^1.0.0" + } + }, + "dotenv": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-7.0.0.tgz", + "integrity": "sha1-or481Sc2ZzIG6KhftSEO6ilijnw=", + "dev": true + }, + "dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha1-P7rwIL/XlIhAcuomsel5HUWmKfA=", + "dev": true + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "dev": true + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha1-Kk31MX9sz9kfhtb9JdjYoQO4gwk=", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" } }, - "crypto-random-string": { + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "easy-stack": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", - "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", + "resolved": "https://registry.npmjs.org/easy-stack/-/easy-stack-1.0.0.tgz", + "integrity": "sha1-EskbMIWjfwuqM26UhurEv5Tj54g=", "dev": true }, - "css": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", - "integrity": "sha1-xkZ1XHOXHyu6amAeLPL9cbEpiSk=", + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", "dev": true, "requires": { - "inherits": "^2.0.3", - "source-map": "^0.6.1", - "source-map-resolve": "^0.5.2", - "urix": "^0.1.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", - "dev": true - } + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" } }, - "css-color-names": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", - "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, - "css-declaration-sorter": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz", - "integrity": "sha1-wZiUD2OnbX42wecQGLABchBUyyI=", + "ejs": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.2.tgz", + "integrity": "sha1-OjLGPRzRbREmbNRwOxT+xOdKtPY=", + "dev": true + }, + "electron": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/electron/-/electron-5.0.8.tgz", + "integrity": "sha1-skBybOnjUQ068wqYFIbJhQRixxg=", "dev": true, "requires": { - "postcss": "^7.0.1", - "timsort": "^0.3.0" + "@types/node": "^10.12.18", + "electron-download": "^4.1.0", + "extract-zip": "^1.0.3" + }, + "dependencies": { + "@types/node": { + "version": "10.14.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.13.tgz", + "integrity": "sha1-rHhtYjhgrfOaP1HWKUgKrNam7sc=", + "dev": true + } } }, - "css-loader": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-1.0.1.tgz", - "integrity": "sha1-aIW7UjOzXsR7AGBX2gHMZAtref4=", + "electron-builder": { + "version": "20.44.4", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-20.44.4.tgz", + "integrity": "sha1-xHmB3fSG1YLArg9NUwyDEBCqytc=", "dev": true, "requires": { - "babel-code-frame": "^6.26.0", - "css-selector-tokenizer": "^0.7.0", - "icss-utils": "^2.1.0", - "loader-utils": "^1.0.2", - "lodash": "^4.17.11", - "postcss": "^6.0.23", - "postcss-modules-extract-imports": "^1.2.0", - "postcss-modules-local-by-default": "^1.2.0", - "postcss-modules-scope": "^1.1.0", - "postcss-modules-values": "^1.3.0", - "postcss-value-parser": "^3.3.0", - "source-list-map": "^2.0.0" + "app-builder-lib": "20.44.4", + "bluebird-lst": "^1.0.9", + "builder-util": "10.1.2", + "builder-util-runtime": "8.2.5", + "chalk": "^2.4.2", + "dmg-builder": "6.7.2", + "fs-extra-p": "^8.0.2", + "is-ci": "^2.0.0", + "lazy-val": "^1.0.4", + "read-config-file": "3.2.2", + "sanitize-filename": "^1.6.1", + "update-notifier": "^3.0.0", + "yargs": "^13.2.4" }, "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha1-YcgswyisYOZ3ZF+XkFTrmLwOMyQ=", + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha1-Z6npZL4xpR4V5QENWObxKDQAL0Y=", + "dev": true + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha1-a8YzQYGBDgS1wis9WJ/cpVAmQEw=", "dev": true, "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" + "ci-info": "^2.0.0" } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", - "dev": true } } }, - "css-parse": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", - "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", + "electron-chromedriver": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/electron-chromedriver/-/electron-chromedriver-5.0.1.tgz", + "integrity": "sha1-DBAqSC8WvUf1T83SOM9kIQOV/0o=", "dev": true, "requires": { - "css": "^2.0.0" + "electron-download": "^4.1.1", + "extract-zip": "^1.6.7" } }, - "css-select": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.0.2.tgz", - "integrity": "sha1-q0OGzsnh9miFVWSxfDcztDsqXt4=", + "electron-download": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/electron-download/-/electron-download-4.1.1.tgz", + "integrity": "sha1-AuaVVnBcxFblIPngNVVu1aAV6+g=", "dev": true, "requires": { - "boolbase": "^1.0.0", - "css-what": "^2.1.2", - "domutils": "^1.7.0", - "nth-check": "^1.0.2" - } - }, - "css-select-base-adapter": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", - "integrity": "sha1-Oy/0lyzDYquIVhUHqVQIoUMhNdc=", - "dev": true + "debug": "^3.0.0", + "env-paths": "^1.0.0", + "fs-extra": "^4.0.1", + "minimist": "^1.2.0", + "nugget": "^2.0.1", + "path-exists": "^3.0.0", + "rc": "^1.2.1", + "semver": "^5.4.1", + "sumchecker": "^2.0.2" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha1-DYUhIuW8W+tFP7Ao6cDJvzY0DJQ=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + } + } }, - "css-selector-tokenizer": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz", - "integrity": "sha1-oXcnGovKUBkXL0+JH8bu2cv2jV0=", + "electron-osx-sign": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.4.11.tgz", + "integrity": "sha1-g3dzL+eyB5afJktnWC7kcCnOCS8=", "dev": true, "requires": { - "cssesc": "^0.1.0", - "fastparse": "^1.1.1", - "regexpu-core": "^1.0.0" + "bluebird": "^3.5.0", + "compare-version": "^0.1.2", + "debug": "^2.6.8", + "isbinaryfile": "^3.0.2", + "minimist": "^1.2.0", + "plist": "^3.0.1" }, "dependencies": { - "cssesc": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", - "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=", - "dev": true - }, - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - }, - "regexpu-core": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", - "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" + "ms": "2.0.0" } }, - "regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", - "dev": true - }, - "regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "isbinaryfile": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", + "integrity": "sha1-XW3vPt6/boyoyunDAYOoBLX4voA=", "dev": true, "requires": { - "jsesc": "~0.5.0" + "buffer-alloc": "^1.2.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, - "css-tree": { - "version": "1.0.0-alpha.33", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.33.tgz", - "integrity": "sha1-lw4g5akfejeN3Q/FjQtsjU876T4=", + "electron-publish": { + "version": "20.44.4", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-20.44.4.tgz", + "integrity": "sha1-+CbeN4jE44SLf269LDrLkQodZsw=", "dev": true, "requires": { - "mdn-data": "2.0.4", - "source-map": "^0.5.3" + "bluebird-lst": "^1.0.9", + "builder-util": "~10.1.2", + "builder-util-runtime": "^8.2.5", + "chalk": "^2.4.2", + "fs-extra-p": "^8.0.2", + "lazy-val": "^1.0.4", + "mime": "^2.4.4" } }, - "css-unit-converter": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.1.tgz", - "integrity": "sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY=", - "dev": true - }, - "css-value": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/css-value/-/css-value-0.0.1.tgz", - "integrity": "sha1-Xv1sLupeof1rasV+wEJ7GEUkJOo=", - "dev": true - }, - "css-what": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", - "integrity": "sha1-ptdgRXM2X+dGhsPzEcVlE9iChfI=", - "dev": true - }, - "cssesc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", - "integrity": "sha1-OxO9G7HLNuG8taTc0n9UxdyzVwM=", + "electron-to-chromium": { + "version": "1.4.788", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.788.tgz", + "integrity": "sha512-ubp5+Ev/VV8KuRoWnfP2QF2Bg+O2ZFdb49DiiNbz2VmgkIqrnyYaqIOqj8A6K/3p1xV0QcU5hBQ1+BmB6ot1OA==", "dev": true }, - "cssnano": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz", - "integrity": "sha1-CsQfCxPRPUZUh+ERt3jULaYxuLI=", + "elliptic": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.0.tgz", + "integrity": "sha1-K47UyJG33jIA4UQSpbgkjHr1Bco=", "dev": true, "requires": { - "cosmiconfig": "^5.0.0", - "cssnano-preset-default": "^4.0.7", - "is-resolvable": "^1.0.0", - "postcss": "^7.0.0" + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" } }, - "cssnano-preset-default": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz", - "integrity": "sha1-UexmLM/KD4izltzZZ5zbkxvhf3Y=", - "dev": true, - "requires": { - "css-declaration-sorter": "^4.0.1", - "cssnano-util-raw-cache": "^4.0.1", - "postcss": "^7.0.0", - "postcss-calc": "^7.0.1", - "postcss-colormin": "^4.0.3", - "postcss-convert-values": "^4.0.1", - "postcss-discard-comments": "^4.0.2", - "postcss-discard-duplicates": "^4.0.2", - "postcss-discard-empty": "^4.0.1", - "postcss-discard-overridden": "^4.0.1", - "postcss-merge-longhand": "^4.0.11", - "postcss-merge-rules": "^4.0.3", - "postcss-minify-font-values": "^4.0.2", - "postcss-minify-gradients": "^4.0.2", - "postcss-minify-params": "^4.0.2", - "postcss-minify-selectors": "^4.0.2", - "postcss-normalize-charset": "^4.0.1", - "postcss-normalize-display-values": "^4.0.2", - "postcss-normalize-positions": "^4.0.2", - "postcss-normalize-repeat-style": "^4.0.2", - "postcss-normalize-string": "^4.0.2", - "postcss-normalize-timing-functions": "^4.0.2", - "postcss-normalize-unicode": "^4.0.1", - "postcss-normalize-url": "^4.0.1", - "postcss-normalize-whitespace": "^4.0.2", - "postcss-ordered-values": "^4.1.2", - "postcss-reduce-initial": "^4.0.3", - "postcss-reduce-transforms": "^4.0.2", - "postcss-svgo": "^4.0.2", - "postcss-unique-selectors": "^4.0.1" - } + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha1-kzoEBShgyF6DwSJHnEdIqOTHIVY=", + "dev": true }, - "cssnano-util-get-arguments": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz", - "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=", + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", "dev": true }, - "cssnano-util-get-match": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz", - "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=", + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", "dev": true }, - "cssnano-util-raw-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz", - "integrity": "sha1-sm1f1fcqEd/np4RvtMZyYPlr8oI=", + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=", "dev": true, "requires": { - "postcss": "^7.0.0" + "once": "^1.4.0" } }, - "cssnano-util-same-parent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz", - "integrity": "sha1-V0CC+yhZ0ttDOFWDXZqEVuoYu/M=", - "dev": true - }, - "csso": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/csso/-/csso-3.5.1.tgz", - "integrity": "sha1-e564vmFiiXPBsmHhadLwJACOdYs=", - "dev": true, + "engine.io": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.3.2.tgz", + "integrity": "sha512-AsaA9KG7cWPXWHp5FvHdDWY3AMWeZ8x+2pUVLcn71qE5AtAzgGbxuclOytygskw8XGmiQafTmnI9Bix3uihu2w==", "requires": { - "css-tree": "1.0.0-alpha.29" + "accepts": "~1.3.4", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "ws": "~6.1.0" }, "dependencies": { - "css-tree": { - "version": "1.0.0-alpha.29", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.29.tgz", - "integrity": "sha1-P6nU7zFCy9HDAedmTB81K9gvWjk=", - "dev": true, - "requires": { - "mdn-data": "~1.1.0", - "source-map": "^0.5.3" + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" } }, - "mdn-data": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-1.1.4.tgz", - "integrity": "sha1-ULXU/8RXUnZXPE7tuHgIEqhBnwE=", - "dev": true + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "ws": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", + "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", + "requires": { + "async-limiter": "~1.0.0" + } } } }, - "current-script-polyfill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/current-script-polyfill/-/current-script-polyfill-1.0.0.tgz", - "integrity": "sha1-8xz35PPiGLBybnOMqSoC00iO9hU=", - "dev": true - }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, + "engine.io-client": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.3.2.tgz", + "integrity": "sha512-y0CPINnhMvPuwtqXfsGuWE8BB66+B6wTtCofQDRecMQPYX3MYUZXFNKDhdrSe3EVjgOu4V3rxdeqN/Tr91IgbQ==", "requires": { - "array-find-index": "^1.0.1" + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.1", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~6.1.0", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + }, + "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "ws": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", + "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", + "requires": { + "async-limiter": "~1.0.0" + } + } } }, - "cyclist": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", - "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", - "dev": true + "engine.io-parser": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", + "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "enhanced-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", + "integrity": "sha1-Qcfgv9/nSsH/4eV61qXGyfN0Kn8=", "dev": true, "requires": { - "assert-plus": "^1.0.0" + "graceful-fs": "^4.1.2", + "memory-fs": "^0.4.0", + "tapable": "^1.0.0" } }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha1-vfpzUplmTfr9NFKe1PhSKidf6lY=", "dev": true }, - "de-indent": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", - "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=", + "env-paths": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-1.0.0.tgz", + "integrity": "sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA=", "dev": true }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=", + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha1-RoTXF3mtOa8Xfj8AeZb3xnyFJhg=", + "dev": true, "requires": { - "ms": "^2.1.1" + "prr": "~1.0.1" } }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true - }, - "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha1-tKxAZIEH/c3PriQvQovqihTU8b8=", "dev": true, "requires": { - "mimic-response": "^1.0.0" + "is-arrayish": "^0.2.1" } }, - "deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", - "dev": true - }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha1-xPp8lUBKF6nD6Mp+FTcxK3NjMKw=", - "dev": true - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "deepmerge": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz", - "integrity": "sha1-EEmdhohEza1P7ghC34x/bwyVp1M=", - "dev": true - }, - "default-gateway": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-5.0.2.tgz", - "integrity": "sha1-0tihPW/uQG2TZdGeya3MuKYLgrM=", + "error-stack-parser": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.2.tgz", + "integrity": "sha1-Sujbqiv5CotFBwe5FJ3KvKE1Ug0=", "dev": true, "requires": { - "execa": "^1.0.0", - "ip-regex": "^2.1.0" + "stackframe": "^1.0.4" } }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "es-abstract": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", + "integrity": "sha1-rIYUX91QmdjdSVWMy6Lq+biOJOk=", "dev": true, "requires": { - "clone": "^1.0.2" + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" } }, - "defer-to-connect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.0.2.tgz", - "integrity": "sha1-S651ijFLA0rjOQK1qsJajdaoYz4=", - "dev": true - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE=", + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha1-7fckeAM0VujdqO8J4ArZZQcH83c=", "dev": true, "requires": { - "object-keys": "^1.0.12" + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" } }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=", + "escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", + "integrity": "sha1-oeOsGq5KP72Clvz496tzFMu2q+o=", "dev": true, "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, + "@babel/code-frame": "^7.0.0", + "ajv": "^6.9.1", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^4.0.3", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^5.0.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.2.2", + "js-yaml": "^3.13.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0" + }, "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "acorn": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz", + "integrity": "sha1-PthCLW3sCeYSHMeoQ8qGozCoa1E=", + "dev": true + }, + "acorn-jsx": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", + "integrity": "sha1-MqBk/ZJUKSFqCbFBECv90YX65A4=", + "dev": true, + "requires": {} + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha1-kAlISfCTfy7twkJdDSip5fDLrZ4=", + "dev": true + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha1-rd6+rXKmV023g2OdyHoSF3OXOWE=", "dev": true, "requires": { - "kind-of": "^6.0.0" + "esutils": "^2.0.2" } }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "espree": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha1-XWUm+k/H8HiKXPdbFfMDI+L4H3o=", "dev": true, "requires": { - "kind-of": "^6.0.0" + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" } }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha1-ywP3QL764D6k0oPK7SdBqD8zVJU=", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" } - } - } - }, - "del": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha1-no8RciLqRKMf86FWwEm5kFKp8LQ=", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "globby": "^6.1.0", - "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", - "p-map": "^2.0.0", - "pify": "^4.0.1", - "rimraf": "^2.6.3" - }, - "dependencies": { - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha1-yg9u+m3T1WEzP7FFFQZcL6/fQ5w=", "dev": true, "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "flat-cache": "^2.0.1" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha1-XSltbwS9pEpGMKMBQTvbwuwIXsA=", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha1-dQ49tYYgh7RzfrrIIH/9HvJ7Jfw=", + "dev": true + }, + "import-fresh": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", + "integrity": "sha1-bTP6Hc7235MPrgA0RvM0Fa+QURg=", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "inquirer": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.0.tgz", + "integrity": "sha1-IwMxfvyaTqfsLi32+GVptzSsz0I=", + "dev": true, + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" }, "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha1-jRnTHPYySCtYkEn4KB+T28uk0H8=", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha1-SrzYUq0y3Xuqv+m0DgCjbbXzkuY=", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha1-ys12k0YaY3pXiNkqfdT7oGjoFjY=", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true } } - } - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "des.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", - "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, - "detect-node": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", - "integrity": "sha1-AU7o+PZpxcWAI9pkuBecCDooxGw=", - "dev": true - }, - "dev-null": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dev-null/-/dev-null-0.1.1.tgz", - "integrity": "sha1-WiBc48Ky73e2I41roXnrdMag6Bg=", - "dev": true - }, - "diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha1-QOjumPVaIUlgcUaSHGPhrl89KHU=", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } - }, - "dir-glob": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", - "integrity": "sha1-+gnwaUFTyJGLGLoN6vrpR2n8UMQ=", - "dev": true, - "requires": { - "path-type": "^3.0.0" + }, + "table": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.4.tgz", + "integrity": "sha1-bg+I/a42knk9EHf9FypGZ6/phqY=", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha1-InZ74htirxCBV0MG9prFG2IgOWE=", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha1-CADhRSO5I6OH5BUSPIZWFqrg9cM=", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + } } }, - "dmg-builder": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-6.7.2.tgz", - "integrity": "sha1-S6SVXn818VnOU8aNdNPqdIdfmv0=", + "eslint-loader": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-2.2.1.tgz", + "integrity": "sha1-KLnBLaVAV68IReKmEScBova/gzc=", "dev": true, "requires": { - "app-builder-lib": "~20.44.4", - "bluebird-lst": "^1.0.9", - "builder-util": "~10.1.2", - "fs-extra-p": "^8.0.2", - "iconv-lite": "^0.4.24", - "js-yaml": "^3.13.1", - "parse-color": "^1.0.0", - "sanitize-filename": "^1.6.1" + "loader-fs-cache": "^1.0.0", + "loader-utils": "^1.0.2", + "object-assign": "^4.0.1", + "object-hash": "^1.1.4", + "rimraf": "^2.6.1" } }, - "dns-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", - "dev": true - }, - "dns-packet": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", - "integrity": "sha1-EqpCaYEHW+UAuRDu3NC0fdfe2lo=", + "eslint-plugin-vue": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-5.2.3.tgz", + "integrity": "sha1-PudZfYI7VHiASy/rqYY7G3QnOWE=", "dev": true, "requires": { - "ip": "^1.1.0", - "safe-buffer": "^5.0.1" + "vue-eslint-parser": "^5.0.0" + }, + "dependencies": { + "acorn": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz", + "integrity": "sha1-PthCLW3sCeYSHMeoQ8qGozCoa1E=", + "dev": true + }, + "acorn-jsx": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", + "integrity": "sha1-MqBk/ZJUKSFqCbFBECv90YX65A4=", + "dev": true, + "requires": {} + }, + "espree": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-4.1.0.tgz", + "integrity": "sha1-co1UUeD9FWwEOEp62J7VH/VOsl8=", + "dev": true, + "requires": { + "acorn": "^6.0.2", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "vue-eslint-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-5.0.0.tgz", + "integrity": "sha1-APTk2pTsl0uCGib/DtD3p4QCuKE=", + "dev": true, + "requires": { + "debug": "^4.1.0", + "eslint-scope": "^4.0.0", + "eslint-visitor-keys": "^1.0.0", + "espree": "^4.1.0", + "esquery": "^1.0.1", + "lodash": "^4.17.11" + } + } } }, - "dns-txt": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", - "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha1-ygODMxD2iJoyZHgaqC5j65z+eEg=", "dev": true, "requires": { - "buffer-indexof": "^1.0.0" + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" } }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha1-XNAfwQFiG0LEzX9dGmYkNxbT850=", + "eslint-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.0.tgz", + "integrity": "sha1-4sPI26doQl+JfPD55R/i4kFIXUw=", "dev": true, - "optional": true, "requires": { - "esutils": "^2.0.2" + "eslint-visitor-keys": "^1.0.0" } }, - "dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha1-ZyGp2u4uKTaClVtq/kFncWJ7t2g=", - "dev": true, - "requires": { - "utila": "~0.4" - } + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha1-PzGA+y4pEBdxastMnW1bXDSmqB0=", + "dev": true }, - "dom-serializer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", - "integrity": "sha1-HsQFnihLq+027sKUHUqXChic58A=", + "espree": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha1-sPRHGHyKi+2US4FaZgvd9d610ac=", "dev": true, + "optional": true, "requires": { - "domelementtype": "^1.3.0", - "entities": "^1.1.1" + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" } }, - "domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha1-PTH1AZGmdJ3RN1p/Ui6CPULlTto=", - "dev": true - }, - "domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha1-0EjESzew0Qp/Kj1f7j9DM9eQSB8=", + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha1-E7BM2z5sXRnfkatph6hpVhmwqnE=", "dev": true }, - "domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha1-iAUJfpM9ZehVRvcm1g9euItE+AM=", + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha1-QGxRZYsfWZGl+bYrHcJbAOPlxwg=", "dev": true, "requires": { - "domelementtype": "1" + "estraverse": "^4.0.0" } }, - "domutils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", - "integrity": "sha1-Vuo0HoNOBuZ0ivehyyXaZ+qfjCo=", + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha1-AHo7n9vCs7uH5IeeoZyS/b05Qs8=", "dev": true, "requires": { - "dom-serializer": "0", - "domelementtype": "1" + "estraverse": "^4.1.0" } }, - "dot-prop": { + "estraverse": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", - "integrity": "sha1-HxngwuGqDjJ5fEl5nyg3rGr2nFc=", - "dev": true, - "requires": { - "is-obj": "^1.0.0" - } + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true }, - "dotenv": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-7.0.0.tgz", - "integrity": "sha1-or481Sc2ZzIG6KhftSEO6ilijnw=", + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, - "dotenv-expand": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", - "integrity": "sha1-P7rwIL/XlIhAcuomsel5HUWmKfA=", - "dev": true - }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", - "dev": true - }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true - }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha1-Kk31MX9sz9kfhtb9JdjYoQO4gwk=", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", "dev": true }, - "easy-stack": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/easy-stack/-/easy-stack-1.0.0.tgz", - "integrity": "sha1-EskbMIWjfwuqM26UhurEv5Tj54g=", + "event-pubsub": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/event-pubsub/-/event-pubsub-4.3.0.tgz", + "integrity": "sha1-9o2Ba8KfHsAsU53FjI3UDOcss24=", "dev": true }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } + "eventemitter2": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-4.1.2.tgz", + "integrity": "sha1-DhqEd6+CGm7zmVsxG/dMI6UkfxU=" }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "eventemitter3": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", + "integrity": "sha1-LT1I+cNGaY/Og6hdfWZOmFNd9uc=", "dev": true }, - "ejs": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.2.tgz", - "integrity": "sha1-OjLGPRzRbREmbNRwOxT+xOdKtPY=", + "events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", + "integrity": "sha1-mgoN+vYok9krh1uPJpjKQRSXPog=", "dev": true }, - "electron": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/electron/-/electron-5.0.8.tgz", - "integrity": "sha1-skBybOnjUQ068wqYFIbJhQRixxg=", + "eventsource": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz", + "integrity": "sha1-j7xyyT/NNAiAkLwKTmT0tc7m2NA=", "dev": true, "requires": { - "@types/node": "^10.12.18", - "electron-download": "^4.1.0", - "extract-zip": "^1.0.3" - }, - "dependencies": { - "@types/node": { - "version": "10.14.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.13.tgz", - "integrity": "sha1-rHhtYjhgrfOaP1HWKUgKrNam7sc=", - "dev": true - } + "original": "^1.0.0" } }, - "electron-builder": { - "version": "20.44.4", - "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-20.44.4.tgz", - "integrity": "sha1-xHmB3fSG1YLArg9NUwyDEBCqytc=", + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha1-f8vbGY3HGVlDLv4ThCaE4FJaywI=", "dev": true, "requires": { - "app-builder-lib": "20.44.4", - "bluebird-lst": "^1.0.9", - "builder-util": "10.1.2", - "builder-util-runtime": "8.2.5", - "chalk": "^2.4.2", - "dmg-builder": "6.7.2", - "fs-extra-p": "^8.0.2", - "is-ci": "^2.0.0", - "lazy-val": "^1.0.4", - "read-config-file": "3.2.2", - "sanitize-filename": "^1.6.1", - "update-notifier": "^3.0.0", - "yargs": "^13.2.4" - }, - "dependencies": { - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha1-Z6npZL4xpR4V5QENWObxKDQAL0Y=", - "dev": true - }, - "is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha1-a8YzQYGBDgS1wis9WJ/cpVAmQEw=", - "dev": true, - "requires": { - "ci-info": "^2.0.0" - } - } + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" } }, - "electron-chromedriver": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/electron-chromedriver/-/electron-chromedriver-5.0.1.tgz", - "integrity": "sha1-DBAqSC8WvUf1T83SOM9kIQOV/0o=", + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha1-xiNqW7TfbW8V6I5/AXeYIWdJ3dg=", "dev": true, "requires": { - "electron-download": "^4.1.1", - "extract-zip": "^1.6.7" + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" } }, - "electron-download": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/electron-download/-/electron-download-4.1.1.tgz", - "integrity": "sha1-AuaVVnBcxFblIPngNVVu1aAV6+g=", + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "requires": { - "debug": "^3.0.0", - "env-paths": "^1.0.0", - "fs-extra": "^4.0.1", - "minimist": "^1.2.0", - "nugget": "^2.0.1", - "path-exists": "^3.0.0", - "rc": "^1.2.1", - "semver": "^5.4.1", - "sumchecker": "^2.0.2" + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "dependencies": { "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.0.0" } }, - "fs-extra": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", - "integrity": "sha1-DYUhIuW8W+tFP7Ao6cDJvzY0DJQ=", + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, - "electron-osx-sign": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.4.11.tgz", - "integrity": "sha1-g3dzL+eyB5afJktnWC7kcCnOCS8=", + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha1-RJH8OGBc9R+GKdOcK10Cb5ikwTQ=", "dev": true, "requires": { - "bluebird": "^3.5.0", - "compare-version": "^0.1.2", - "debug": "^2.6.8", - "isbinaryfile": "^3.0.2", - "minimist": "^1.2.0", - "plist": "^3.0.1" + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" }, "dependencies": { "debug": { @@ -22220,154 +22395,140 @@ "ms": "2.0.0" } }, - "isbinaryfile": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", - "integrity": "sha1-XW3vPt6/boyoyunDAYOoBLX4voA=", - "dev": true, - "requires": { - "buffer-alloc": "^1.2.0" - } - }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha1-QdwaAV49WB8WIXdr4xr7KHapsbw=", + "dev": true } } }, - "electron-publish": { - "version": "20.44.4", - "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-20.44.4.tgz", - "integrity": "sha1-+CbeN4jE44SLf269LDrLkQodZsw=", - "dev": true, - "requires": { - "bluebird-lst": "^1.0.9", - "builder-util": "~10.1.2", - "builder-util-runtime": "^8.2.5", - "chalk": "^2.4.2", - "fs-extra-p": "^8.0.2", - "lazy-val": "^1.0.4", - "mime": "^2.4.4" - } - }, - "electron-to-chromium": { - "version": "1.3.200", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.200.tgz", - "integrity": "sha1-ePuFi0ZiaejrRtMaUlYvAMhlEn8=", + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo=", "dev": true }, - "elliptic": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.0.tgz", - "integrity": "sha1-K47UyJG33jIA4UQSpbgkjHr1Bco=", + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } } }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha1-kzoEBShgyF6DwSJHnEdIqOTHIVY=", - "dev": true - }, - "emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", - "dev": true - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true - }, - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=", + "external-editor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha1-BFURz9jRM/OEZnPRBHwVTiFK09U=", "dev": true, "requires": { - "once": "^1.4.0" + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" } }, - "engine.io": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.3.2.tgz", - "integrity": "sha512-AsaA9KG7cWPXWHp5FvHdDWY3AMWeZ8x+2pUVLcn71qE5AtAzgGbxuclOytygskw8XGmiQafTmnI9Bix3uihu2w==", + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=", + "dev": true, "requires": { - "accepts": "~1.3.4", - "base64id": "1.0.0", - "cookie": "0.3.1", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.0", - "ws": "~6.1.0" + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "dependencies": { - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, "requires": { - "ms": "2.0.0" + "is-extendable": "^0.1.0" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, - "ws": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", - "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "dev": true, "requires": { - "async-limiter": "~1.0.0" + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } } } }, - "engine.io-client": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.3.2.tgz", - "integrity": "sha512-y0CPINnhMvPuwtqXfsGuWE8BB66+B6wTtCofQDRecMQPYX3MYUZXFNKDhdrSe3EVjgOu4V3rxdeqN/Tr91IgbQ==", + "extract-zip": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", + "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=", + "dev": true, "requires": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.1", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "~6.1.0", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" + "concat-stream": "1.6.2", + "debug": "2.6.9", + "mkdirp": "0.5.1", + "yauzl": "2.4.1" }, "dependencies": { - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" - }, "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "dev": true, "requires": { "ms": "2.0.0" } @@ -22375,1859 +22536,452 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "ws": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", - "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", - "requires": { - "async-limiter": "~1.0.0" - } + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, - "engine.io-parser": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", - "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.5", - "has-binary2": "~1.0.2" - } + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true }, - "enhanced-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", - "integrity": "sha1-Qcfgv9/nSsH/4eV61qXGyfN0Kn8=", + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fast-glob": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", + "integrity": "sha1-aVOFfDr6R1//ku5gFdUtpwpM050=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.4.0", - "tapable": "^1.0.0" + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" } }, - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha1-vfpzUplmTfr9NFKe1PhSKidf6lY=", + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", "dev": true }, - "env-paths": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-1.0.0.tgz", - "integrity": "sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA=", + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, - "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha1-RoTXF3mtOa8Xfj8AeZb3xnyFJhg=", + "fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", "dev": true, "requires": { - "prr": "~1.0.1" + "punycode": "^1.3.2" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + } } }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha1-tKxAZIEH/c3PriQvQovqihTU8b8=", + "fastparse": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", + "integrity": "sha1-kXKMWllC7O2FMSg8eUQe5BIsNak=", + "dev": true + }, + "faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", "dev": true, "requires": { - "is-arrayish": "^0.2.1" + "websocket-driver": ">=0.5.1" } }, - "error-stack-parser": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.2.tgz", - "integrity": "sha1-Sujbqiv5CotFBwe5FJ3KvKE1Ug0=", + "fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", "dev": true, "requires": { - "stackframe": "^1.0.4" + "pend": "~1.2.0" } }, - "es-abstract": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", - "integrity": "sha1-rIYUX91QmdjdSVWMy6Lq+biOJOk=", + "figgy-pudding": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", + "integrity": "sha1-hiRwESkBxyeg5JWoB0S9W6odZ5A=", + "dev": true + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", "dev": true, "requires": { - "es-to-primitive": "^1.2.0", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "is-callable": "^1.1.4", - "is-regex": "^1.0.4", - "object-keys": "^1.0.12" + "escape-string-regexp": "^1.0.5" } }, - "es-to-primitive": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", - "integrity": "sha1-7fckeAM0VujdqO8J4ArZZQcH83c=", + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", "dev": true, + "optional": true, "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" } }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "eslint": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", - "integrity": "sha1-oeOsGq5KP72Clvz496tzFMu2q+o=", + "file-loader": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-3.0.1.tgz", + "integrity": "sha1-+OC6C1mZGLUa3+RdZtHnca1WD6o=", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.9.1", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "eslint-scope": "^4.0.3", - "eslint-utils": "^1.3.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^5.0.1", - "esquery": "^1.0.1", - "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", - "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.7.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "inquirer": "^6.2.2", - "js-yaml": "^3.13.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.11", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", - "progress": "^2.0.0", - "regexpp": "^2.0.1", - "semver": "^5.5.1", - "strip-ansi": "^4.0.0", - "strip-json-comments": "^2.0.1", - "table": "^5.2.3", - "text-table": "^0.2.0" + "loader-utils": "^1.0.2", + "schema-utils": "^1.0.0" }, "dependencies": { - "acorn": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz", - "integrity": "sha1-PthCLW3sCeYSHMeoQ8qGozCoa1E=", - "dev": true - }, - "acorn-jsx": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", - "integrity": "sha1-MqBk/ZJUKSFqCbFBECv90YX65A4=", - "dev": true, - "requires": {} - }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha1-kAlISfCTfy7twkJdDSip5fDLrZ4=", - "dev": true - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha1-rd6+rXKmV023g2OdyHoSF3OXOWE=", + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", "dev": true, "requires": { - "esutils": "^2.0.2" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } - }, - "espree": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", - "integrity": "sha1-XWUm+k/H8HiKXPdbFfMDI+L4H3o=", + } + } + }, + "filesize": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz", + "integrity": "sha1-CQuz7gG2+AGoqL6Z0xcQs0Irsxc=", + "dev": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "acorn": "^6.0.7", - "acorn-jsx": "^5.0.0", - "eslint-visitor-keys": "^1.0.0" + "is-extendable": "^0.1.0" } - }, - "external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha1-ywP3QL764D6k0oPK7SdBqD8zVJU=", + } + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha1-t+fQAP/RGTjQ/bBTUG9uur6fWH0=", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" + "ms": "2.0.0" } }, - "file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha1-yg9u+m3T1WEzP7FFFQZcL6/fQ5w=", - "dev": true, - "requires": { - "flat-cache": "^2.0.1" - } - }, - "flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha1-XSltbwS9pEpGMKMBQTvbwuwIXsA=", - "dev": true, - "requires": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - } - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha1-dQ49tYYgh7RzfrrIIH/9HvJ7Jfw=", - "dev": true - }, - "import-fresh": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", - "integrity": "sha1-bTP6Hc7235MPrgA0RvM0Fa+QURg=", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "inquirer": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.0.tgz", - "integrity": "sha1-IwMxfvyaTqfsLi32+GVptzSsz0I=", - "dev": true, - "requires": { - "ansi-escapes": "^3.2.0", - "chalk": "^2.4.2", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.3", - "figures": "^2.0.0", - "lodash": "^4.17.12", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rxjs": "^6.4.0", - "string-width": "^2.1.0", - "strip-ansi": "^5.1.0", - "through": "^2.3.6" - }, - "dependencies": { - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha1-jRnTHPYySCtYkEn4KB+T28uk0H8=", - "dev": true - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha1-SrzYUq0y3Xuqv+m0DgCjbbXzkuY=", + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true - }, - "slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha1-ys12k0YaY3pXiNkqfdT7oGjoFjY=", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - } - } - }, - "table": { - "version": "5.4.4", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.4.tgz", - "integrity": "sha1-bg+I/a42knk9EHf9FypGZ6/phqY=", - "dev": true, - "requires": { - "ajv": "^6.10.2", - "lodash": "^4.17.14", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" - }, - "dependencies": { - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha1-InZ74htirxCBV0MG9prFG2IgOWE=", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "write": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", - "integrity": "sha1-CADhRSO5I6OH5BUSPIZWFqrg9cM=", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } } } }, - "eslint-loader": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-2.2.1.tgz", - "integrity": "sha1-KLnBLaVAV68IReKmEScBova/gzc=", - "dev": true, - "requires": { - "loader-fs-cache": "^1.0.0", - "loader-utils": "^1.0.2", - "object-assign": "^4.0.1", - "object-hash": "^1.1.4", - "rimraf": "^2.6.1" - } - }, - "eslint-plugin-vue": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-5.2.3.tgz", - "integrity": "sha1-PudZfYI7VHiASy/rqYY7G3QnOWE=", + "find-babel-config": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.2.0.tgz", + "integrity": "sha1-qbezF+tbmGDNqdVHQKjIM3oig6I=", "dev": true, "requires": { - "vue-eslint-parser": "^5.0.0" + "json5": "^0.5.1", + "path-exists": "^3.0.0" }, "dependencies": { - "acorn": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz", - "integrity": "sha1-PthCLW3sCeYSHMeoQ8qGozCoa1E=", + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true - }, - "acorn-jsx": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", - "integrity": "sha1-MqBk/ZJUKSFqCbFBECv90YX65A4=", - "dev": true, - "requires": {} - }, - "espree": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-4.1.0.tgz", - "integrity": "sha1-co1UUeD9FWwEOEp62J7VH/VOsl8=", - "dev": true, - "requires": { - "acorn": "^6.0.2", - "acorn-jsx": "^5.0.0", - "eslint-visitor-keys": "^1.0.0" - } - }, - "vue-eslint-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-5.0.0.tgz", - "integrity": "sha1-APTk2pTsl0uCGib/DtD3p4QCuKE=", - "dev": true, - "requires": { - "debug": "^4.1.0", - "eslint-scope": "^4.0.0", - "eslint-visitor-keys": "^1.0.0", - "espree": "^4.1.0", - "esquery": "^1.0.1", - "lodash": "^4.17.11" - } } } }, - "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha1-ygODMxD2iJoyZHgaqC5j65z+eEg=", + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha1-jQ+UzRP+Q8bHwmGg2GEVypGMBfc=", "dev": true, "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" } }, - "eslint-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.0.tgz", - "integrity": "sha1-4sPI26doQl+JfPD55R/i4kFIXUw=", + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "eslint-visitor-keys": "^1.0.0" + "locate-path": "^2.0.0" } }, - "eslint-visitor-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha1-PzGA+y4pEBdxastMnW1bXDSmqB0=", - "dev": true - }, - "espree": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", - "integrity": "sha1-sPRHGHyKi+2US4FaZgvd9d610ac=", + "flat-cache": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", + "integrity": "sha1-LC73dSXMKSkAff/6HdMUqpyd7m8=", "dev": true, "optional": true, "requires": { - "acorn": "^5.5.0", - "acorn-jsx": "^3.0.0" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha1-E7BM2z5sXRnfkatph6hpVhmwqnE=", - "dev": true - }, - "esquery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha1-QGxRZYsfWZGl+bYrHcJbAOPlxwg=", - "dev": true, - "requires": { - "estraverse": "^4.0.0" - } - }, - "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha1-AHo7n9vCs7uH5IeeoZyS/b05Qs8=", - "dev": true, - "requires": { - "estraverse": "^4.1.0" - } - }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true - }, - "event-pubsub": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/event-pubsub/-/event-pubsub-4.3.0.tgz", - "integrity": "sha1-9o2Ba8KfHsAsU53FjI3UDOcss24=", - "dev": true - }, - "eventemitter2": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-4.1.2.tgz", - "integrity": "sha1-DhqEd6+CGm7zmVsxG/dMI6UkfxU=" - }, - "eventemitter3": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", - "integrity": "sha1-LT1I+cNGaY/Og6hdfWZOmFNd9uc=", - "dev": true - }, - "events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", - "integrity": "sha1-mgoN+vYok9krh1uPJpjKQRSXPog=", - "dev": true - }, - "eventsource": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz", - "integrity": "sha1-j7xyyT/NNAiAkLwKTmT0tc7m2NA=", - "dev": true, - "requires": { - "original": "^1.0.0" - } - }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha1-f8vbGY3HGVlDLv4ThCaE4FJaywI=", - "dev": true, - "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha1-xiNqW7TfbW8V6I5/AXeYIWdJ3dg=", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha1-RJH8OGBc9R+GKdOcK10Cb5ikwTQ=", - "dev": true, - "requires": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha1-QdwaAV49WB8WIXdr4xr7KHapsbw=", - "dev": true - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo=", - "dev": true - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "external-editor": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", - "integrity": "sha1-BFURz9jRM/OEZnPRBHwVTiFK09U=", - "dev": true, - "requires": { - "chardet": "^0.4.0", - "iconv-lite": "^0.4.17", - "tmp": "^0.0.33" - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "extract-zip": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", - "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=", - "dev": true, - "requires": { - "concat-stream": "1.6.2", - "debug": "2.6.9", - "mkdirp": "0.5.1", - "yauzl": "2.4.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true - }, - "fast-glob": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", - "integrity": "sha1-aVOFfDr6R1//ku5gFdUtpwpM050=", - "dev": true, - "requires": { - "@mrmlnc/readdir-enhanced": "^2.2.1", - "@nodelib/fs.stat": "^1.1.2", - "glob-parent": "^3.1.0", - "is-glob": "^4.0.0", - "merge2": "^1.2.3", - "micromatch": "^3.1.10" - } - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fast-url-parser": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", - "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", - "dev": true, - "requires": { - "punycode": "^1.3.2" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "dev": true - } - } - }, - "fastparse": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", - "integrity": "sha1-kXKMWllC7O2FMSg8eUQe5BIsNak=", - "dev": true - }, - "faye-websocket": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - }, - "fd-slicer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", - "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, - "figgy-pudding": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", - "integrity": "sha1-hiRwESkBxyeg5JWoB0S9W6odZ5A=", - "dev": true - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "file-entry-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", - "dev": true, - "optional": true, - "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" - } - }, - "file-loader": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-3.0.1.tgz", - "integrity": "sha1-+OC6C1mZGLUa3+RdZtHnca1WD6o=", - "dev": true, - "requires": { - "loader-utils": "^1.0.2", - "schema-utils": "^1.0.0" - }, - "dependencies": { - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - } - } - }, - "filesize": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz", - "integrity": "sha1-CQuz7gG2+AGoqL6Z0xcQs0Irsxc=", - "dev": true - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha1-t+fQAP/RGTjQ/bBTUG9uur6fWH0=", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "find-babel-config": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.2.0.tgz", - "integrity": "sha1-qbezF+tbmGDNqdVHQKjIM3oig6I=", - "dev": true, - "requires": { - "json5": "^0.5.1", - "path-exists": "^3.0.0" - }, - "dependencies": { - "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true - } - } - }, - "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha1-jQ+UzRP+Q8bHwmGg2GEVypGMBfc=", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "flat-cache": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", - "integrity": "sha1-LC73dSXMKSkAff/6HdMUqpyd7m8=", - "dev": true, - "optional": true, - "requires": { - "circular-json": "^0.3.1", - "graceful-fs": "^4.1.2", - "rimraf": "~2.6.2", - "write": "^0.2.1" - } - }, - "flatted": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", - "integrity": "sha1-aeV8qo8OrLwoHS4stFjUb9tEngg=", - "dev": true - }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha1-jdfYc6G6vCB9lOrQwuDkQnbr8ug=", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "follow-redirects": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz", - "integrity": "sha1-SJ68GY3A5/ZBZ70jsDxMGbV4THY=", - "dev": true, - "requires": { - "debug": "^3.2.6" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha1-3M5SwF9kTymManq5Nr1yTO/786Y=", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", - "dev": true - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true - }, - "friendly-errors-webpack-plugin": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.7.0.tgz", - "integrity": "sha1-78hsu4FiJFZYYaG+ep2E0Kr+oTY=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "error-stack-parser": "^2.0.0", - "string-width": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha1-a+Dem+mYzhavivwkSXue6bfM2a0=", - "dev": true - }, - "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha1-TxicRKoSO4lfcigE9V6iPq3DSOk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-extra-p": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra-p/-/fs-extra-p-8.1.0.tgz", - "integrity": "sha1-eBtxBels88HTyKiKgyFcijHFK64=", - "dev": true, - "requires": { - "bluebird-lst": "^1.0.9", - "fs-extra": "^8.1.0" - }, - "dependencies": { - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha1-SdQ8RaiM2Wd2aMt74bRu/bjS4cA=", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - } - } - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", - "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", - "dev": true, - "optional": true, - "requires": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.12.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.1", - "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "4.1.1", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.3", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.1", - "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.3.5", - "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.1.1", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.3.0", - "integrity": "sha512-QBZu7aAFR0522EyaXZM0FZ9GLpq6lvQ3uq8gteiDUp7wKdy0lSd2hPlgFwVuW1CBkfEs9PfDQsQzZghLs/psdg==", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^4.1.0", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.12.0", - "integrity": "sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.6", - "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.1", - "integrity": "sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.3", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "bundled": true, + "circular-json": "^0.3.1", + "graceful-fs": "^4.1.2", + "rimraf": "~2.6.2", + "write": "^0.2.1" + } + }, + "flatted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha1-aeV8qo8OrLwoHS4stFjUb9tEngg=", + "dev": true + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha1-jdfYc6G6vCB9lOrQwuDkQnbr8ug=", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "follow-redirects": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz", + "integrity": "sha1-SJ68GY3A5/ZBZ70jsDxMGbV4THY=", + "dev": true, + "requires": { + "debug": "^3.2.6" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", "dev": true, - "optional": true, "requires": { - "glob": "^7.1.3" + "ms": "^2.1.1" } + } + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha1-3M5SwF9kTymManq5Nr1yTO/786Y=", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "friendly-errors-webpack-plugin": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.7.0.tgz", + "integrity": "sha1-78hsu4FiJFZYYaG+ep2E0Kr+oTY=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "error-stack-parser": "^2.0.0", + "string-width": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true }, - "safe-buffer": { - "version": "5.1.2", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "bundled": true, - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.0", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "bundled": true, - "dev": true, - "optional": true - }, - "string_decoder": { - "version": "1.1.1", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true }, - "string-width": { - "version": "1.0.2", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "bundled": true, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, - "optional": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, "strip-ansi": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } }, - "strip-json-comments": { - "version": "2.0.1", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.8", - "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "bundled": true, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha1-a+Dem+mYzhavivwkSXue6bfM2a0=", + "dev": true + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha1-TxicRKoSO4lfcigE9V6iPq3DSOk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs-extra-p": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra-p/-/fs-extra-p-8.1.0.tgz", + "integrity": "sha1-eBtxBels88HTyKiKgyFcijHFK64=", + "dev": true, + "requires": { + "bluebird-lst": "^1.0.9", + "fs-extra": "^8.1.0" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha1-SdQ8RaiM2Wd2aMt74bRu/bjS4cA=", "dev": true, - "optional": true, "requires": { - "string-width": "^1.0.2 || 2" + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" } - }, - "wrappy": { - "version": "1.0.2", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.0.3", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "bundled": true, - "dev": true, - "optional": true } } }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -26319,13 +25073,6 @@ "thenify-all": "^1.0.0" } }, - "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true, - "optional": true - }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -26434,13 +25181,10 @@ } }, "node-releases": { - "version": "1.1.26", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.26.tgz", - "integrity": "sha1-8wVj7cXH3CDPUkzIZS/6e+B2KTc=", - "dev": true, - "requires": { - "semver": "^5.3.0" - } + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true }, "normalize-package-data": { "version": "2.5.0", @@ -27089,6 +25833,12 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "dev": true + }, "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -30833,6 +29583,16 @@ "integrity": "sha1-PbZYYA7a7sy+bbXmhNZ+6MKs0Gg=", "dev": true }, + "update-browserslist-db": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", + "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", + "dev": true, + "requires": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + } + }, "update-check": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/update-check/-/update-check-1.5.4.tgz", diff --git a/ros/user_interface/package.xml b/ros/user_interface/package.xml index 7e15081a..77a9ae5c 100644 --- a/ros/user_interface/package.xml +++ b/ros/user_interface/package.xml @@ -1,53 +1,21 @@ - + + user_interface 0.0.0 - The user interface + The user_interface package + Marc-Antoine Maheux + GPL-3.0 license - - - - mamaheux + ament_cmake + rosidl_default_runtime + rosidl_interface_packages - - - - TODO + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - catkin - - roscpp - roscpp - - - - + ament_cmake - diff --git a/ros/user_interface/scripts/web.sh b/ros/user_interface/scripts/web.sh index d53cdf5a..2ec552ef 100755 --- a/ros/user_interface/scripts/web.sh +++ b/ros/user_interface/scripts/web.sh @@ -1,12 +1,12 @@ #!/bin/bash -SCRIPT=`realpath $0` +SCRIPT=`realpath --no-symlinks $0` SCRIPT_PATH=`dirname $SCRIPT` cd $SCRIPT_PATH/.. -PATH=$(npm bin):$PATH -serve -s dist -l 8080 & +chmod +x $SCRIPT_PATH/node_modules/serve/build/main.js +$SCRIPT_PATH/node_modules/serve/build/main.js -S -s $SCRIPT_PATH/dist -l 8080 & SERVER_PID=$! trap "kill ${SERVER_PID}; exit 1" INT sleep 1 diff --git a/ros/utils/audio_utils b/ros/utils/audio_utils index 263d77b6..3828d81b 160000 --- a/ros/utils/audio_utils +++ b/ros/utils/audio_utils @@ -1 +1 @@ -Subproject commit 263d77b6ebf4a4e687c48bcb0b09c544bf5fa7a4 +Subproject commit 3828d81b319f6fd1df43a4f7a45b2a7e765f0d60 diff --git a/ros/utils/cloud_data/CMakeLists.txt b/ros/utils/cloud_data/CMakeLists.txt index 5b3303be..5d287c1c 100644 --- a/ros/utils/cloud_data/CMakeLists.txt +++ b/ros/utils/cloud_data/CMakeLists.txt @@ -1,203 +1,36 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(cloud_data) -## Compile as C++11, supported in ROS Kinetic and newer -# add_compile_options(-std=c++11) - -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - message_generation - rospy - ) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -# add_message_files( -# FILES -# Message1.msg -# Message2.msg -# ) - -## Generate services in the 'srv' folder -add_service_files( - FILES - Location.srv - CurrentLocalWeather.srv - LocalWeatherForecast.srv +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclpy REQUIRED) +find_package(rosidl_default_generators REQUIRED) + +# Generate services +rosidl_generate_interfaces(${PROJECT_NAME} + "srv/CurrentLocalWeather.srv" + "srv/LocalWeatherForecast.srv" + "srv/Location.srv" ) -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -generate_messages() - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( - # INCLUDE_DIRS include - # LIBRARIES cloud_data - # CATKIN_DEPENDS message_generation rospy - # DEPENDS system_lib -) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( - # include - ${catkin_INCLUDE_DIRS} +# Python Nodes +install(PROGRAMS + scripts/cloud_data_node.py + DESTINATION lib/${PROJECT_NAME} ) -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/cloud_data.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -# add_executable(${PROJECT_NAME}_node src/cloud_data_node.cpp) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -# target_link_libraries(${PROJECT_NAME}_node -# ${catkin_LIBRARIES} -# ) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -catkin_install_python(PROGRAMS - scripts/cloud_data_node.py - DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} - ) - -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_cloud_data.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() - -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/utils/cloud_data/README.md b/ros/utils/cloud_data/README.md index 9c713717..394f05eb 100644 --- a/ros/utils/cloud_data/README.md +++ b/ros/utils/cloud_data/README.md @@ -10,8 +10,8 @@ This node gets data location, the current local weather and the local weather fo #### Parameters -- `language` (string): The language for the weather description (en or fr). -- `timeout_s` (double): The request timeout in seconds. +- `language` (string): The language for the weather description (en or fr). The default value is 'en'. +- `timeout_s` (double): The request timeout in seconds. The default value is 10.0. #### Services diff --git a/ros/utils/cloud_data/package.xml b/ros/utils/cloud_data/package.xml index 53a986c0..49ffc651 100644 --- a/ros/utils/cloud_data/package.xml +++ b/ros/utils/cloud_data/package.xml @@ -1,63 +1,24 @@ - + + cloud_data 0.0.0 The cloud_data package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rosidl_default_generators + rclpy - - - - TODO + rosidl_default_runtime + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - message_generation - rospy - rospy - rospy - - - - - + ament_cmake diff --git a/ros/utils/cloud_data/scripts/cloud_data_node.py b/ros/utils/cloud_data/scripts/cloud_data_node.py index e5b037d4..db8b76e0 100755 --- a/ros/utils/cloud_data/scripts/cloud_data_node.py +++ b/ros/utils/cloud_data/scripts/cloud_data_node.py @@ -3,116 +3,135 @@ import os import json -from numpy.lib.function_base import select - import ipinfo import requests -import rospy -from cloud_data.srv import Location, LocationResponse -from cloud_data.srv import CurrentLocalWeather, CurrentLocalWeatherResponse -from cloud_data.srv import LocalWeatherForecast, LocalWeatherForecastResponse +import rclpy +import rclpy.node + +from cloud_data.srv import Location, CurrentLocalWeather, LocalWeatherForecast OPEN_WEATHER_MAP_API_URL = 'https://us-central1-ttop-316419.cloudfunctions.net/weather' -class CloudDataNode: +class CloudDataNode(rclpy.node.Node): def __init__(self): - self._language = rospy.get_param('~language') - self._timeout = rospy.get_param('~timeout_s') - - self._location_service = rospy.Service('cloud_data/location', Location, self._handle_location) - self._current_local_weather_service = rospy.Service('cloud_data/current_local_weather', - CurrentLocalWeather, - self._handle_current_local_weather) - self._local_weather_forecast_service = rospy.Service('cloud_data/local_weather_forecast', - LocalWeatherForecast, - self._handle_local_weather_forecast) - - def _handle_location(self, request): - location = self._get_location() - - return LocationResponse( - city=location.city, - region=location.region, - country_code=location.country, - country_name=location.country_name - ) - - def _handle_current_local_weather(self, request): - location = self._get_location() - weather = self._get_weather(location.latitude, location.longitude) - current_weather = weather['current'] - - if 'wind_gust' in current_weather: - wind_gust = self._mps_to_kph(current_weather['wind_gust']) - else: - wind_gust = -1.0 - - if len(current_weather['weather']) == 0: - weather_description = '' - else: - weather_description = current_weather['weather'][0]['description'] - - return CurrentLocalWeatherResponse( - city=location.city, - region=location.region, - country_code=location.country, - country_name=location.country_name, - - temperature_celsius=current_weather['temp'], - feels_like_temperature_celsius=current_weather['feels_like'], - pressure_kpa=self._hpa_to_kpa(current_weather['pressure']), - humidity_percent=current_weather['humidity'], - clouds_percent=current_weather['clouds'], - visibility_meter=current_weather['visibility'], - wind_speed_kph=self._mps_to_kph(current_weather['wind_speed']), - wind_gust_kph=wind_gust, - weather_description=weather_description - ) - - def _handle_local_weather_forecast(self, request): - location = self._get_location() - weather = self._get_weather(location.latitude, location.longitude) - - if request.relative_day >= len(weather['daily']): - raise ValueError('Invalid relative day') - - daily_weather = weather['daily'][request.relative_day] - - if 'wind_gust' in daily_weather: - wind_gust = self._mps_to_kph(daily_weather['wind_gust']) - else: - wind_gust = -1.0 - - if len(daily_weather['weather']) == 0: - weather_description = '' - else: - weather_description = daily_weather['weather'][0]['description'] - - return LocalWeatherForecastResponse( - city=location.city, - region=location.region, - country_code=location.country, - country_name=location.country_name, - - temperature_morning_celsius=daily_weather['temp']['morn'], - temperature_day_celsius=daily_weather['temp']['day'], - temperature_evening_celsius=daily_weather['temp']['eve'], - temperature_night_celsius=daily_weather['temp']['night'], - - feals_like_temperature_morning_celsius=daily_weather['feels_like']['morn'], - feals_like_temperature_day_celsius=daily_weather['feels_like']['day'], - feals_like_temperature_evening_celsius=daily_weather['feels_like']['eve'], - feals_like_temperature_night_celsius=daily_weather['feels_like']['night'], - - pressure_kpa=self._hpa_to_kpa(daily_weather['pressure']), - humidity_percent=daily_weather['humidity'], - clouds_percent=daily_weather['clouds'], - wind_speed_kph=self._mps_to_kph(daily_weather['wind_speed']), - wind_gust_kph=wind_gust, - weather_description=weather_description - ) + super().__init__('cloud_data_node') + + self._language = self.declare_parameter('language', 'en').get_parameter_value().string_value + self._timeout = self.declare_parameter('timeout_s', 10.0).get_parameter_value().double_value + + self._location_service = self.create_service(Location, 'cloud_data/location', self._handle_location) + self._current_local_weather_service = self.create_service(CurrentLocalWeather, + 'cloud_data/current_local_weather', + self._handle_current_local_weather) + self._local_weather_forecast_service = self.create_service(LocalWeatherForecast, + 'cloud_data/local_weather_forecast', + self._handle_local_weather_forecast) + + def _handle_location(self, request, response): + try: + location = self._get_location() + + response.ok = True + response.city = location.city + response.region = location.region + response.country_code = location.country + response.country_name = location.country_name + except Exception as e: + self.get_logger().error(f'An error occured while retrieving the location: {e}') + response.ok = False + + return response + + def _handle_current_local_weather(self, request, response): + self.get_logger().info(f'Fetching current_local_weather') + try: + location = self._get_location() + weather = self._get_weather(location.latitude, location.longitude) + current_weather = weather['current'] + + if 'wind_gust' in current_weather: + wind_gust = self._mps_to_kph(current_weather['wind_gust']) + else: + wind_gust = -1.0 + + if len(current_weather['weather']) == 0: + weather_description = '' + else: + weather_description = current_weather['weather'][0]['description'] + + response.ok = True + response.city = location.city + response.region = location.region + response.country_code = location.country + response.country_name = location.country_name + + response.temperature_celsius = current_weather['temp'] + response.feels_like_temperature_celsius = current_weather['feels_like'] + response.pressure_kpa = self._hpa_to_kpa(current_weather['pressure']) + response.humidity_percent = float(current_weather['humidity']) + response.clouds_percent = float(current_weather['clouds']) + response.visibility_meter = float(current_weather['visibility']) + response.wind_speed_kph = self._mps_to_kph(current_weather['wind_speed']) + response.wind_gust_kph = wind_gust + response.weather_description = weather_description + except Exception as e: + self.get_logger().error(f'An error occured while retrieving the local weather: {e}') + response.ok = False + + self.get_logger().info(f'Returning current_local_weather, ok: {response.ok}') + return response + + def _handle_local_weather_forecast(self, request, response): + self.get_logger().info(f'Fetching local_weather_forecast') + try: + location = self._get_location() + weather = self._get_weather(location.latitude, location.longitude) + + if request.relative_day >= len(weather['daily']): + raise ValueError('Invalid relative day') + + daily_weather = weather['daily'][request.relative_day] + + if 'wind_gust' in daily_weather: + wind_gust = self._mps_to_kph(daily_weather['wind_gust']) + else: + wind_gust = -1.0 + + if len(daily_weather['weather']) == 0: + weather_description = '' + else: + weather_description = daily_weather['weather'][0]['description'] + + response.ok = True + response.city = location.city + response.region = location.region + response.country_code = location.country + response.country_name = location.country_name + + response.temperature_morning_celsius = daily_weather['temp']['morn'] + response.temperature_day_celsius = daily_weather['temp']['day'] + response.temperature_evening_celsius = daily_weather['temp']['eve'] + response.temperature_night_celsius = daily_weather['temp']['night'] + + response.feals_like_temperature_morning_celsius = daily_weather['feels_like']['morn'] + response.feals_like_temperature_day_celsius = daily_weather['feels_like']['day'] + response.feals_like_temperature_evening_celsius = daily_weather['feels_like']['eve'] + response.feals_like_temperature_night_celsius = daily_weather['feels_like']['night'] + + response.pressure_kpa = self._hpa_to_kpa(daily_weather['pressure']) + response.humidity_percent = float(daily_weather['humidity']) + response.clouds_percent = float(daily_weather['clouds']) + response.wind_speed_kph = self._mps_to_kph(daily_weather['wind_speed']) + response.wind_gust_kph = wind_gust + response.weather_description = weather_description + except Exception as e: + self.get_logger().error(f'An error occured while retrieving the local weather forecast: {e}') + response.ok = False + + self.get_logger().info(f'Returning local_weather_forecast, ok: {response.ok}') + return response def _get_location(self): handler = ipinfo.getHandler() @@ -137,17 +156,22 @@ def _mps_to_kph(self, mps): return mps * 3.6 def run(self): - rospy.spin() + rclpy.spin(self) def main(): - rospy.init_node('cloud_data_node') + rclpy.init() cloud_data_node = CloudDataNode() - cloud_data_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + cloud_data_node.run() + except KeyboardInterrupt: pass + finally: + cloud_data_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/utils/cloud_data/srv/CurrentLocalWeather.srv b/ros/utils/cloud_data/srv/CurrentLocalWeather.srv index 7d138928..a31bc165 100644 --- a/ros/utils/cloud_data/srv/CurrentLocalWeather.srv +++ b/ros/utils/cloud_data/srv/CurrentLocalWeather.srv @@ -1,4 +1,6 @@ --- +bool ok + string city string region string country_code diff --git a/ros/utils/cloud_data/srv/LocalWeatherForecast.srv b/ros/utils/cloud_data/srv/LocalWeatherForecast.srv index 0a8296f6..2a97f3b7 100644 --- a/ros/utils/cloud_data/srv/LocalWeatherForecast.srv +++ b/ros/utils/cloud_data/srv/LocalWeatherForecast.srv @@ -3,6 +3,8 @@ # ... uint64 relative_day --- +bool ok + string city string region string country_code diff --git a/ros/utils/cloud_data/srv/Location.srv b/ros/utils/cloud_data/srv/Location.srv index a328e42f..49e85c7b 100644 --- a/ros/utils/cloud_data/srv/Location.srv +++ b/ros/utils/cloud_data/srv/Location.srv @@ -1,4 +1,6 @@ --- +bool ok + string city string region string country_code diff --git a/ros/utils/dnn_utils/CMakeLists.txt b/ros/utils/dnn_utils/CMakeLists.txt index 7045c4f6..cc7e0493 100644 --- a/ros/utils/dnn_utils/CMakeLists.txt +++ b/ros/utils/dnn_utils/CMakeLists.txt @@ -1,211 +1,41 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(dnn_utils) -## Compile as C++11, supported in ROS Kinetic and newer -# add_compile_options(-std=c++11) +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - rospy - ) +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclpy REQUIRED) -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -catkin_python_setup() +# Python Librairies +ament_python_install_package(${PROJECT_NAME}) +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../../../tools/dnn_training DESTINATION ${PYTHON_INSTALL_DIR}) -################################################ -## Declare ROS messages, services and actions ## -################################################ -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -# add_message_files( -# FILES -# Message1.msg -# Message2.msg -# ) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -# generate_messages( -# DEPENDENCIES -# std_msgs # Or other packages containing msgs -# ) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( - # INCLUDE_DIRS include - # LIBRARIES dnn_utils - # CATKIN_DEPENDS rospy - # DEPENDS system_lib +# Python Nodes +install(PROGRAMS + scripts/test.py + DESTINATION lib/${PROJECT_NAME} ) -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( - # include - ${catkin_INCLUDE_DIRS} -) - -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/dnn_utils.cpp -# ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -# add_executable(${PROJECT_NAME}_node src/dnn_utils_node.cpp) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -# target_link_libraries(${PROJECT_NAME}_node -# ${catkin_LIBRARIES} -# ) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -# catkin_install_python(PROGRAMS -# scripts/my_python_script -# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_dnn_utils.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() - -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) - - +# DNN Models add_custom_target( dnn_utils_export_models ALL COMMAND scripts/export_models.bash WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) +install(DIRECTORY models DESTINATION share/${PROJECT_NAME}) + +ament_package() diff --git a/ros/utils/dnn_utils/README.md b/ros/utils/dnn_utils/README.md index df56d042..7b68281f 100644 --- a/ros/utils/dnn_utils/README.md +++ b/ros/utils/dnn_utils/README.md @@ -14,7 +14,7 @@ This neural network classifies a sound to one class and extracts an embedding. I This neural network detects objects, classifies them and extracts embeddings for them. It takes as input a RGB image. The model is a modified version of `YOLOv4-tiny (COCO)` or `YOLOv7 (COCO)`. -`YOLOv7 (COCO)` is training with [this repository](https://github.com/mamaheux/descriptor-yolov7). +`YOLOv7 (COCO)` is trained with [this repository](https://github.com/mamaheux/descriptor-yolov7). ### `FaceDescriptorExtractor` diff --git a/ros/utils/dnn_utils/src/dnn_utils/__init__.py b/ros/utils/dnn_utils/dnn_utils/__init__.py similarity index 100% rename from ros/utils/dnn_utils/src/dnn_utils/__init__.py rename to ros/utils/dnn_utils/dnn_utils/__init__.py diff --git a/ros/utils/dnn_utils/src/dnn_utils/audio_transforms.py b/ros/utils/dnn_utils/dnn_utils/audio_transforms.py similarity index 100% rename from ros/utils/dnn_utils/src/dnn_utils/audio_transforms.py rename to ros/utils/dnn_utils/dnn_utils/audio_transforms.py diff --git a/ros/utils/dnn_utils/src/dnn_utils/descriptor_yolo.py b/ros/utils/dnn_utils/dnn_utils/descriptor_yolo.py similarity index 96% rename from ros/utils/dnn_utils/src/dnn_utils/descriptor_yolo.py rename to ros/utils/dnn_utils/dnn_utils/descriptor_yolo.py index 93bcf6f8..b2602947 100644 --- a/ros/utils/dnn_utils/src/dnn_utils/descriptor_yolo.py +++ b/ros/utils/dnn_utils/dnn_utils/descriptor_yolo.py @@ -5,10 +5,10 @@ import torch.nn.functional as F import torchaudio -from dnn_utils.dnn_model import PACKAGE_PATH, DnnModel +from dnn_utils.dnn_model import DNN_TRAINING_PATHS, PACKAGE_PATH, DnnModel from dnn_utils.yolo import COCO_CLASS_NAMES, OBJECTS365_CLASS_NAMES -sys.path.append(os.path.join(PACKAGE_PATH, '..', '..', '..', 'tools', 'dnn_training')) +sys.path.extend(DNN_TRAINING_PATHS) from object_detection.modules.yolo_layer import X_INDEX, Y_INDEX, W_INDEX, H_INDEX, CONFIDENCE_INDEX, CLASSES_INDEX from object_detection.filter_yolo_predictions import group_predictions, filter_yolo_predictions diff --git a/ros/utils/dnn_utils/src/dnn_utils/dnn_model.py b/ros/utils/dnn_utils/dnn_utils/dnn_model.py similarity index 90% rename from ros/utils/dnn_utils/src/dnn_utils/dnn_model.py rename to ros/utils/dnn_utils/dnn_utils/dnn_model.py index f403c709..626ec6b4 100644 --- a/ros/utils/dnn_utils/src/dnn_utils/dnn_model.py +++ b/ros/utils/dnn_utils/dnn_utils/dnn_model.py @@ -1,3 +1,4 @@ +import os import time import torch @@ -8,10 +9,14 @@ except ImportError: TORCH2TRT_FOUND = False -import rospkg +import ament_index_python.packages -PACKAGE_PATH = rospkg.RosPack().get_path('dnn_utils') +DNN_TRAINING_PATHS = [ + os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'dnn_training'), + os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', '..', '..', '..', 'tools', 'dnn_training'), +] +PACKAGE_PATH = ament_index_python.packages.get_package_share_directory('dnn_utils') class DnnModel: diff --git a/ros/utils/dnn_utils/src/dnn_utils/face_descriptor_extractor.py b/ros/utils/dnn_utils/dnn_utils/face_descriptor_extractor.py similarity index 92% rename from ros/utils/dnn_utils/src/dnn_utils/face_descriptor_extractor.py rename to ros/utils/dnn_utils/dnn_utils/face_descriptor_extractor.py index 6593daa7..314b5dc4 100644 --- a/ros/utils/dnn_utils/src/dnn_utils/face_descriptor_extractor.py +++ b/ros/utils/dnn_utils/dnn_utils/face_descriptor_extractor.py @@ -10,9 +10,9 @@ import torch.nn.functional as F import torchvision.transforms as transforms -from dnn_utils.dnn_model import PACKAGE_PATH, DnnModel +from dnn_utils.dnn_model import DNN_TRAINING_PATHS, PACKAGE_PATH, DnnModel -sys.path.append(os.path.join(PACKAGE_PATH, '..', '..', '..', 'tools', 'dnn_training')) +sys.path.extend(DNN_TRAINING_PATHS) from face_recognition.datasets.align_faces import get_landmarks_from_pose, cv2_transform_to_theta @@ -22,8 +22,8 @@ class FaceDescriptorExtractor(DnnModel): def __init__(self, inference_type=None): - torch_script_model_path = os.path.join(PACKAGE_PATH, 'models', f'face_descriptor_open_face_e256.ts.pth') - tensor_rt_model_path = os.path.join(PACKAGE_PATH, 'models', f'face_descriptor_open_face_e256.trt.pth') + torch_script_model_path = os.path.join(PACKAGE_PATH, 'models', 'face_descriptor_open_face_e256.ts.pth') + tensor_rt_model_path = os.path.join(PACKAGE_PATH, 'models', 'face_descriptor_open_face_e256.trt.pth') sample_input = torch.ones((1, 3, IMAGE_SIZE[0], IMAGE_SIZE[1])) super(FaceDescriptorExtractor, self).__init__(torch_script_model_path, tensor_rt_model_path, sample_input, diff --git a/ros/utils/dnn_utils/src/dnn_utils/multiclass_audio_descriptor_extractor.py b/ros/utils/dnn_utils/dnn_utils/multiclass_audio_descriptor_extractor.py similarity index 100% rename from ros/utils/dnn_utils/src/dnn_utils/multiclass_audio_descriptor_extractor.py rename to ros/utils/dnn_utils/dnn_utils/multiclass_audio_descriptor_extractor.py diff --git a/ros/utils/dnn_utils/src/dnn_utils/pose_estimator.py b/ros/utils/dnn_utils/dnn_utils/pose_estimator.py similarity index 95% rename from ros/utils/dnn_utils/src/dnn_utils/pose_estimator.py rename to ros/utils/dnn_utils/dnn_utils/pose_estimator.py index 691b690a..1aa5e472 100644 --- a/ros/utils/dnn_utils/src/dnn_utils/pose_estimator.py +++ b/ros/utils/dnn_utils/dnn_utils/pose_estimator.py @@ -5,9 +5,9 @@ import torch.nn.functional as F import torchvision.transforms as transforms -from dnn_utils.dnn_model import PACKAGE_PATH, DnnModel +from dnn_utils.dnn_model import DNN_TRAINING_PATHS, PACKAGE_PATH, DnnModel -sys.path.append(os.path.join(PACKAGE_PATH, '..', '..', '..', 'tools', 'dnn_training')) +sys.path.extend(DNN_TRAINING_PATHS) from pose_estimation.pose_estimator import get_coordinates diff --git a/ros/utils/dnn_utils/src/dnn_utils/semantic_segmentation_network.py b/ros/utils/dnn_utils/dnn_utils/semantic_segmentation_network.py similarity index 100% rename from ros/utils/dnn_utils/src/dnn_utils/semantic_segmentation_network.py rename to ros/utils/dnn_utils/dnn_utils/semantic_segmentation_network.py diff --git a/ros/utils/dnn_utils/src/dnn_utils/ttop_keyword_spotter.py b/ros/utils/dnn_utils/dnn_utils/ttop_keyword_spotter.py similarity index 100% rename from ros/utils/dnn_utils/src/dnn_utils/ttop_keyword_spotter.py rename to ros/utils/dnn_utils/dnn_utils/ttop_keyword_spotter.py diff --git a/ros/utils/dnn_utils/src/dnn_utils/voice_descriptor_extractor.py b/ros/utils/dnn_utils/dnn_utils/voice_descriptor_extractor.py similarity index 100% rename from ros/utils/dnn_utils/src/dnn_utils/voice_descriptor_extractor.py rename to ros/utils/dnn_utils/dnn_utils/voice_descriptor_extractor.py diff --git a/ros/utils/dnn_utils/src/dnn_utils/yolo.py b/ros/utils/dnn_utils/dnn_utils/yolo.py similarity index 98% rename from ros/utils/dnn_utils/src/dnn_utils/yolo.py rename to ros/utils/dnn_utils/dnn_utils/yolo.py index 15260302..ca883868 100644 --- a/ros/utils/dnn_utils/src/dnn_utils/yolo.py +++ b/ros/utils/dnn_utils/dnn_utils/yolo.py @@ -4,9 +4,9 @@ import torch import torch.nn.functional as F -from dnn_utils.dnn_model import PACKAGE_PATH, DnnModel +from dnn_utils.dnn_model import DNN_TRAINING_PATHS, PACKAGE_PATH, DnnModel -sys.path.append(os.path.join(PACKAGE_PATH, '..', '..', '..', 'tools', 'dnn_training')) +sys.path.extend(DNN_TRAINING_PATHS) from object_detection.modules.yolo_layer import X_INDEX, Y_INDEX, W_INDEX, H_INDEX, CONFIDENCE_INDEX, CLASSES_INDEX from object_detection.filter_yolo_predictions import group_predictions, filter_yolo_predictions_by_classes diff --git a/ros/utils/dnn_utils/package.xml b/ros/utils/dnn_utils/package.xml index 4515cc72..db176515 100644 --- a/ros/utils/dnn_utils/package.xml +++ b/ros/utils/dnn_utils/package.xml @@ -1,62 +1,25 @@ - + + dnn_utils 0.0.0 The dnn_utils package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rosidl_default_generators + rclpy + ament_index_python - - - - TODO + rosidl_default_runtime + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - rospy - rospy - rospy - - - - - + ament_cmake diff --git a/ros/utils/dnn_utils/scripts/test.py b/ros/utils/dnn_utils/scripts/test.py index 5ebad9f2..70acfbda 100755 --- a/ros/utils/dnn_utils/scripts/test.py +++ b/ros/utils/dnn_utils/scripts/test.py @@ -6,7 +6,8 @@ import torch -import rospy +import rclpy +import rclpy.node from dnn_utils import DescriptorYolo, Yolo, PoseEstimator, FaceDescriptorExtractor from dnn_utils import MulticlassAudioDescriptorExtractor, VoiceDescriptorExtractor, TTopKeywordSpotter @@ -178,7 +179,7 @@ def test_ttop_keyword_spotter(): print('mean(abs(cpu_class_probabilities - torch_gpu_class_probabilities)) =', mean_abs_diff(cpu_class_probabilities, torch_gpu_class_probabilities)) print('mean(abs(cpu_class_probabilities - trt_gpu_class_probabilities))) =', - mean_abs_diff(cpu_class_probabilities, trt_gpu_class_probabilities)) + mean_abs_diff(cpu_class_probabilities, trt_gpu_class_probabilities)) def test_semantic_segmentation_network(dataset): @@ -201,27 +202,32 @@ def test_semantic_segmentation_network(dataset): def main(): - rospy.init_node('dnn_utils_test', disable_signals=True) - - launch_test(test_descriptor_yolo, 'yolo_v4_tiny_coco') - launch_test(test_descriptor_yolo, 'yolo_v7_coco') - launch_test(test_yolo, 'yolo_v4_coco') - launch_test(test_yolo, 'yolo_v4_tiny_coco') - launch_test(test_yolo, 'yolo_v7_coco') - launch_test(test_yolo, 'yolo_v7_tiny_coco') - launch_test(test_yolo, 'yolo_v7_objects365') - launch_test(test_pose_estimator) - launch_test(test_face_descriptor_extractor) - launch_test(test_multiclass_audio_descriptor_extractor) - launch_test(test_voice_descriptor_extractor) - launch_test(test_ttop_keyword_spotter) - launch_test(test_semantic_segmentation_network, 'coco') - launch_test(test_semantic_segmentation_network, 'kitchen_open_images') - launch_test(test_semantic_segmentation_network, 'person_other_open_images') - + rclpy.init() + node = rclpy.node.Node('dnn_utils_test') -if __name__ == '__main__': try: - main() + launch_test(test_descriptor_yolo, 'yolo_v4_tiny_coco') + launch_test(test_descriptor_yolo, 'yolo_v7_coco') + launch_test(test_yolo, 'yolo_v4_coco') + launch_test(test_yolo, 'yolo_v4_tiny_coco') + launch_test(test_yolo, 'yolo_v7_coco') + launch_test(test_yolo, 'yolo_v7_tiny_coco') + launch_test(test_yolo, 'yolo_v7_objects365') + launch_test(test_pose_estimator) + launch_test(test_face_descriptor_extractor) + launch_test(test_multiclass_audio_descriptor_extractor) + launch_test(test_voice_descriptor_extractor) + launch_test(test_ttop_keyword_spotter) + launch_test(test_semantic_segmentation_network, 'coco') + launch_test(test_semantic_segmentation_network, 'kitchen_open_images') + launch_test(test_semantic_segmentation_network, 'person_other_open_images') except KeyboardInterrupt: pass + finally: + node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/utils/dnn_utils/setup.py b/ros/utils/dnn_utils/setup.py deleted file mode 100644 index 5eaf642b..00000000 --- a/ros/utils/dnn_utils/setup.py +++ /dev/null @@ -1,12 +0,0 @@ -## ! DO NOT MANUALLY INVOKE THIS setup.py, USE CATKIN INSTEAD - -from distutils.core import setup -from catkin_pkg.python_setup import generate_distutils_setup - -# fetch values from package.xml -setup_args = generate_distutils_setup( - packages=['dnn_utils'], - package_dir={'': 'src'}, -) - -setup(**setup_args) diff --git a/ros/utils/hbba_lite b/ros/utils/hbba_lite index f3e17afb..7382ff62 160000 --- a/ros/utils/hbba_lite +++ b/ros/utils/hbba_lite @@ -1 +1 @@ -Subproject commit f3e17afb6d1e3d855576e7dc4e3a2b7dae835581 +Subproject commit 7382ff6237688d963e58c57993f0cd852cebf1a4 diff --git a/ros/utils/opentera-webrtc-ros b/ros/utils/opentera-webrtc-ros new file mode 160000 index 00000000..201c1e0a --- /dev/null +++ b/ros/utils/opentera-webrtc-ros @@ -0,0 +1 @@ +Subproject commit 201c1e0af91f49ea4a2698b4729d7d81d7d2a31a diff --git a/ros/utils/recorders/3rd_party/SQLiteCpp b/ros/utils/recorders/3rd_party/SQLiteCpp index 4e3d36af..bcb4c78f 160000 --- a/ros/utils/recorders/3rd_party/SQLiteCpp +++ b/ros/utils/recorders/3rd_party/SQLiteCpp @@ -1 +1 @@ -Subproject commit 4e3d36af2d4a612d548f5959532a7b97c9724e6b +Subproject commit bcb4c78fed6628f150c28fa6377c2b0430f7f99b diff --git a/ros/utils/recorders/CMakeLists.txt b/ros/utils/recorders/CMakeLists.txt index a7f35eb2..6c4d2647 100644 --- a/ros/utils/recorders/CMakeLists.txt +++ b/ros/utils/recorders/CMakeLists.txt @@ -1,136 +1,44 @@ -cmake_minimum_required(VERSION 3.14.2) +cmake_minimum_required(VERSION 3.5) project(recorders) -## Compile as C++11, supported in ROS Kinetic and newer -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - audio_utils - rospy - sensor_msgs - hbba_lite - roscpp - video_analyzer - audio_analyzer - talk - speech_to_text - tf -) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -# add_message_files( -# FILES -# Message1.msg -# Message2.msg -# ) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -# generate_messages( -# DEPENDENCIES -# sensor_msgs -# ) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( - INCLUDE_DIRS - ${CMAKE_CURRENT_SOURCE_DIR}/3rd_party/SQLiteCpp/include - include - LIBRARIES SQLiteCpp perception_logger - # CATKIN_DEPENDS audio_utils rospy sensor_msgs - # DEPENDS system_lib -) +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclcpp REQUIRED) +find_package(rclpy REQUIRED) +find_package(audio_utils_msgs REQUIRED) +find_package(sensor_msgs REQUIRED) +find_package(geometry_msgs REQUIRED) +find_package(hbba_lite REQUIRED) +find_package(perception_msgs REQUIRED) +find_package(behavior_msgs REQUIRED) +find_package(tf2 REQUIRED) +find_package(tf2_ros REQUIRED) +find_package(tf2_msgs REQUIRED) +find_package(tf2_geometry_msgs REQUIRED) + +# C++ Library add_subdirectory(3rd_party/SQLiteCpp) +install(DIRECTORY 3rd_party/SQLiteCpp/include/ DESTINATION include) +install(TARGETS SQLiteCpp DESTINATION lib) -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations include_directories( include 3rd_party/SQLiteCpp/include - ${catkin_INCLUDE_DIRS} ) ## Declare a C++ library @@ -147,105 +55,66 @@ add_library(perception_logger src/perception_logger/sqlite/SQLiteSpeechLogger.cpp src/perception_logger/sqlite/SQLiteHbbaStrategyStateLogger.cpp ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -add_dependencies(perception_logger ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide -add_executable(perception_logger_node src/perception_logger_node.cpp) - -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -target_link_libraries(perception_logger - ${catkin_LIBRARIES} - SQLiteCpp +ament_target_dependencies(perception_logger rclcpp) +target_link_libraries(perception_logger SQLiteCpp sqlite3) +install(DIRECTORY include/ DESTINATION include) +install(TARGETS perception_logger DESTINATION lib) + +ament_export_include_directories(include) +ament_export_libraries(perception_logger SQLiteCpp sqlite3 dl) + +install( + TARGETS perception_logger + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + RUNTIME DESTINATION bin + INCLUDES DESTINATION include ) -target_link_libraries(perception_logger_node - ${catkin_LIBRARIES} - SQLiteCpp - perception_logger +add_executable(perception_logger_node src/perception_logger_node.cpp) +ament_target_dependencies(perception_logger_node + rclcpp + audio_utils_msgs + sensor_msgs + geometry_msgs + hbba_lite + hbba_lite_msgs + perception_msgs + behavior_msgs + tf2 + tf2_ros + tf2_msgs + tf2_geometry_msgs ) +target_link_libraries(perception_logger_node perception_logger SQLiteCpp sqlite3 dl) +install(TARGETS perception_logger_node DESTINATION lib/${PROJECT_NAME}) -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -catkin_install_python(PROGRAMS +# Python Nodes +install(PROGRAMS scripts/video_recorder_node.py - DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} + DESTINATION lib/${PROJECT_NAME} ) -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -catkin_add_gtest(perception_logger-test - test/perception_logger/main.cpp - test/perception_logger/BinarySerializationTests.cpp - test/perception_logger/PerceptionLoggerTests.cpp - test/perception_logger/AudioAnalysisLoggerTests.cpp - test/perception_logger/VideoAnalysisLoggerTests.cpp - test/perception_logger/SpeechLoggerTests.cpp - test/perception_logger/HbbaStrategyStateLoggerTests.cpp - test/perception_logger/sqlite/SQLiteMigrationTests.cpp - test/perception_logger/sqlite/SQLitePerceptionLoggerTests.cpp - test/perception_logger/sqlite/SQLiteAudioAnalysisLoggerTests.cpp - test/perception_logger/sqlite/SQLiteVideoAnalysisLoggerTests.cpp - test/perception_logger/sqlite/SQLiteSpeechLoggerTests.cpp - test/perception_logger/sqlite/SQLiteHbbaStrategyStateLoggerTests.cpp -) -if(TARGET perception_logger-test) - target_link_libraries(perception_logger-test perception_logger ${catkin_LIBRARIES}) - target_include_directories(perception_logger-test PUBLIC test/perception_logger) +# Tests +if(BUILD_TESTING) + find_package(ament_cmake_gtest REQUIRED) + ament_add_gtest(${PROJECT_NAME}_test + test/perception_logger/main.cpp + test/perception_logger/BinarySerializationTests.cpp + test/perception_logger/PerceptionLoggerTests.cpp + test/perception_logger/AudioAnalysisLoggerTests.cpp + test/perception_logger/VideoAnalysisLoggerTests.cpp + test/perception_logger/SpeechLoggerTests.cpp + test/perception_logger/HbbaStrategyStateLoggerTests.cpp + test/perception_logger/sqlite/SQLiteMigrationTests.cpp + test/perception_logger/sqlite/SQLitePerceptionLoggerTests.cpp + test/perception_logger/sqlite/SQLiteAudioAnalysisLoggerTests.cpp + test/perception_logger/sqlite/SQLiteVideoAnalysisLoggerTests.cpp + test/perception_logger/sqlite/SQLiteSpeechLoggerTests.cpp + test/perception_logger/sqlite/SQLiteHbbaStrategyStateLoggerTests.cpp + ) + ament_target_dependencies(${PROJECT_NAME}_test rclcpp) + target_link_libraries(${PROJECT_NAME}_test perception_logger SQLiteCpp sqlite3 dl) endif() -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/utils/recorders/README.md b/ros/utils/recorders/README.md index e3511bcd..ef8b47d5 100644 --- a/ros/utils/recorders/README.md +++ b/ros/utils/recorders/README.md @@ -8,23 +8,29 @@ This node records an image topic and an audio topic. #### Parameters - `output_directory` (string): The output directory where to save the recorded files. - `filename_prefix` (string): The filename prefix of the recorded files. - - `video_format` (string): The image encoding of the image topic (`rgb8` or `bgr8`). - - `video_width` (int): The image width of the image topic. - - `video_height` (int): The image height of the image topic. - - `video_codec` (string): The video codec to use (`h264`, `h265`, `vp8` or `vp9`). - - `video_bitrate` (int): The video codec bitrate (bits/s). - - `video_delay_s` (double): The video delay in seconds. - - `audio_format` (string): The audio format of the audio topic. - - `audio_channel_count` (int): The channel count of the audio topic. - - `audio_sampling_frequency` (int): The sampling frequency of the audio topic. - - `audio_codec` (string): The audio codec to use (`aac`, or `mp3`). + - `video_stream_name` (string): The video stream name. + - `video_stream_format` (string): The image encoding of the image topic (`rgb8` or `bgr8`). + - `video_stream_width` (int): The image width of the image topic. + - `video_stream_height` (int): The image height of the image topic. + - `video_stream_framerate` (int): The video frame rate. + - `video_stream_codec` (string): The video codec to use (`h264`, `h265`, `vp8`, `vp9` or `av1`). + - `video_stream_bitrate` (int): The video codec bitrate (bits/s). + - `video_stream_delay_s` (double): The video delay in seconds. + - `video_stream_language_code` (string): The video stream language code. + - `audio_stream_name` (string): The audio stream name + - `audio_stream_format` (string): The audio format of the audio topic. + - `audio_stream_channel_count` (int): The channel count of the audio topic. + - `audio_stream_sampling_frequency` (int): The sampling frequency of the audio topic. + - `audio_stream_codec` (string): The audio codec to use (`aac`, or `mp3`). + - `audio_stream_merge_channels` (bool): Indicates to merge the audio channels. + - `audio_stream_language_code` (string): The audio stream language code. #### Subscribed Topics - - `image` ([sensor_msgs/Image](http://docs.ros.org/en/noetic/api/sensor_msgs/html/msg/Image.html)): The image topic to record. - - `audio` ([audio_utils/AudioFrame](https://github.com/introlab/audio_utils/blob/main/msg/AudioFrame.msg)): The audio topic to record. + - `video_{video_stream_name}` ([sensor_msgs/Image](https://docs.ros.org/en/humble/p/sensor_msgs/interfaces/msg/Image.html)): The image topic to record. + - `audio_{audio_stream_name}` ([audio_utils_msgs/AudioFrame](https://github.com/introlab/audio_utils/blob/ros2/audio_utils_msgs/msg/AudioFrame.msg)): The audio topic to record. #### Services - - `video_recorder/filter_state` ([hbba_lite/SetOnOffFilterState](../../hbba_lite/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the recording. + - `video_recorder/filter_state` ([hbba_lite_srvs/SetOnOffFilterState](../../utils/hbba_lite/hbba_lite_srvs/srv/SetOnOffFilterState.srv)): The HBBA filter state service to enable or disable the recording. ### `perception_logger_node` This node logs the video analysis messages and the audio analysis messages into a SQLite database. @@ -34,7 +40,7 @@ This node logs the video analysis messages and the audio analysis messages into - `frame_id` (string): The frame id of the positions and directions in the database. #### Subscribed Topics - - `video_analysis` ([video_analyzer/VideoAnalysis](../../perceptions/video_analyzer/msg/VideoAnalysis.msg)): The video analysis containing the detected objects. The video analysis must contain 3d positions. - - `audio_analysis` ([audio_analyzer/AudioAnalysis](../../perceptions/audio_analyzer/msg/AudioAnalysis.msg)): The audio analysis containing the audio classes, voice embedding and the sound direction. - - `talk/text` ([talk/Text](../../behaviors/talk/msg/Text.msg)): The text spoken by the robot. - - `speech_to_text/text` ([speech_to_text/Text](../../perceptions/speech_to_text/msg/Transcript.msg)): The text spoken by the human. + - `video_analysis` ([perception_msgs/VideoAnalysis](../../perceptions/perception_msgs/msg/VideoAnalysis.msg)): The video analysis containing the detected objects. The video analysis must contain 3d positions. + - `audio_analysis` ([perception_msgs/AudioAnalysis](../../perceptions/perception_msgs/msg/AudioAnalysis.msg)): The audio analysis containing the audio classes, voice embedding and the sound direction. + - `talk/text` ([talk/Text](../../behaviors/behavior_msgs/msg/Text.msg)): The text spoken by the robot. + - `speech_to_text/transcript` ([perception_msgs/Transcript](../../perceptions/perception_msgs/msg/Transcript.msg)): The text spoken by the human. diff --git a/ros/utils/recorders/include/perception_logger/PerceptionLogger.h b/ros/utils/recorders/include/perception_logger/PerceptionLogger.h index 00850ca2..63b3795c 100644 --- a/ros/utils/recorders/include/perception_logger/PerceptionLogger.h +++ b/ros/utils/recorders/include/perception_logger/PerceptionLogger.h @@ -3,7 +3,7 @@ #include -#include +#include struct __attribute__((packed)) Position { @@ -130,10 +130,7 @@ struct Timestamp explicit Timestamp(int64_t unixEpochMs) : unixEpochMs(unixEpochMs) {} - Timestamp(const ros::Time& time) - : unixEpochMs{static_cast(time.sec) * 1'000 + static_cast(time.nsec) / 1'000'000} - { - } + Timestamp(const rclcpp::Time& time) : unixEpochMs{static_cast(time.seconds() * 1'000)} {} }; #endif diff --git a/ros/utils/recorders/package.xml b/ros/utils/recorders/package.xml index 99a2a359..5ebcc9f2 100644 --- a/ros/utils/recorders/package.xml +++ b/ros/utils/recorders/package.xml @@ -1,89 +1,37 @@ - + + recorders 0.0.0 The recorders package + Marc-Antoine Maheux + GPL-3.0 license + + ament_cmake + rosidl_default_generators + + rclcpp + rclpy + audio_utils_msgs + sensor_msgs + geometry_msgs + hbba_lite + perception_msgs + behavior_msgs + tf2 + tf2_ros + tf2_msgs + tf2_geometry_msgs + + rosidl_default_runtime + ros2launch + rosidl_interface_packages + + ament_lint_auto + ament_lint_common + ament_cmake_gtest - - - - marc-antoine - - - - - - TODO - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - audio_utils - rospy - sensor_msgs - hbba_lite - roscpp - video_analyzer - audio_analyzer - talk - speech_to_text - tf - audio_utils - rospy - sensor_msgs - hbba_lite - roscpp - video_analyzer - audio_analyser - talk - speech_to_text - tf - audio_utils - rospy - sensor_msgs - hbba_lite - roscpp - video_analyzer - audio_analyser - talk - speech_to_text - tf - - - - - + ament_cmake diff --git a/ros/utils/recorders/scripts/video_recorder_node.py b/ros/utils/recorders/scripts/video_recorder_node.py index 0b94315a..17e1d018 100755 --- a/ros/utils/recorders/scripts/video_recorder_node.py +++ b/ros/utils/recorders/scripts/video_recorder_node.py @@ -27,14 +27,24 @@ from gi.repository import Gst # type: ignore from gi.repository import GLib # type: ignore -import rospy +import rclpy +import rclpy.node +import rclpy.logging +import rclpy.subscription -from audio_utils.msg import AudioFrame +from audio_utils_msgs.msg import AudioFrame from sensor_msgs.msg import Image import hbba_lite +NODE_NAME = 'video_recorder_node' + + +def get_logger(): + return rclpy.logging.get_logger(NODE_NAME) + + def apply(func: Callable, iter: Iterable) -> None: for x in iter: func(x) @@ -184,28 +194,28 @@ def check_parameters(parameters: VideoStreamParameters, index: int) -> None: sould_exit = False if 'name' not in parameters: debug_str = f'at index |{index}|' - rospy.logerr(f'Video stream parameters {debug_str} must have a name') + get_logger().error(f'Video stream parameters {debug_str} must have a name') sould_exit = True else: debug_str = f'for name |{parameters["name"]}|' if 'format' not in parameters: - rospy.logerr(f'Video stream parameters {debug_str} must have a format') + get_logger().error(f'Video stream parameters {debug_str} must have a format') sould_exit = True if 'width' not in parameters: - rospy.logerr(f'Video stream parameters {debug_str} must have a width') + get_logger().error(f'Video stream parameters {debug_str} must have a width') sould_exit = True if 'height' not in parameters: - rospy.logerr(f'Video stream parameters {debug_str} must have a height') + get_logger().error(f'Video stream parameters {debug_str} must have a height') sould_exit = True if 'framerate' not in parameters: - rospy.logerr(f'Video stream parameters {debug_str} must have a framerate') + get_logger().error(f'Video stream parameters {debug_str} must have a framerate') sould_exit = True if 'codec' not in parameters: - rospy.logerr(f'Video stream parameters {debug_str} must have a codec') + get_logger().error(f'Video stream parameters {debug_str} must have a codec') sould_exit = True if 'bitrate' not in parameters: - rospy.logerr(f'Video stream parameters {debug_str} must have a bitrate') + get_logger().error(f'Video stream parameters {debug_str} must have a bitrate') sould_exit = True if sould_exit: @@ -263,26 +273,26 @@ def check_parameters(parameters: AudioStreamParameters, index: int) -> None: sould_exit = False if 'name' not in parameters: debug_str = f'at index |{index}|' - rospy.logerr(f'Audio stream parameters {debug_str} must have a name') + get_logger().error(f'Audio stream parameters {debug_str} must have a name') sould_exit = True else: debug_str = f'for name |{parameters["name"]}|' if 'format' not in parameters: - rospy.logerr(f'Audio stream parameters {debug_str} must have a format') + get_logger().error(f'Audio stream parameters {debug_str} must have a format') sould_exit = True if 'channel_count' not in parameters: - rospy.logerr( + get_logger().error( f'Audio stream parameters {debug_str} must have a channel_count' ) sould_exit = True if 'sampling_frequency' not in parameters: - rospy.logerr( + get_logger().error( f'Audio stream parameters {debug_str} must have a sampling_frequency' ) sould_exit = True if 'codec' not in parameters: - rospy.logerr(f'Audio stream parameters {debug_str} must have a codec') + get_logger().error(f'Audio stream parameters {debug_str} must have a codec') sould_exit = True if sould_exit: @@ -338,34 +348,51 @@ def _is_valid_language_code(language_code: str) -> bool: ) @staticmethod - def from_parameters() -> 'VideoRecorderConfiguration': + def from_parameters(node: rclpy.node.Node) -> 'VideoRecorderConfiguration': + + output_directory = node.declare_parameter('output_directory', '').get_parameter_value().string_value + filename_prefix = node.declare_parameter('filename_prefix', '').get_parameter_value().string_value + + video_stream_parameters = { + 'name': node.declare_parameter('video_stream_name', '').get_parameter_value().string_value, + 'format': node.declare_parameter('video_stream_format', '').get_parameter_value().string_value, + 'width': node.declare_parameter('video_stream_width', 0).get_parameter_value().integer_value, + 'height': node.declare_parameter('video_stream_height', 0).get_parameter_value().integer_value, + 'framerate': node.declare_parameter('video_stream_framerate', 0).get_parameter_value().integer_value, + 'codec': node.declare_parameter('video_stream_codec', '').get_parameter_value().string_value, + 'bitrate': node.declare_parameter('video_stream_bitrate', 0).get_parameter_value().integer_value, + 'delay_s': node.declare_parameter('video_stream_delay_s', 0.0).get_parameter_value().double_value, + 'language_code': node.declare_parameter('video_stream_language_code', 'eng').get_parameter_value().string_value, + } - output_directory = cast(str, rospy.get_param('~output_directory')) - filename_prefix = cast( - str, rospy.get_param('~filename_prefix', '') # type: ignore - ) - video_streams = [ - VideoStreamConfiguration.from_parameters(video_stream, index) for index, video_stream in enumerate(rospy.get_param(f'~video_streams')) # type: ignore - ] - audio_streams = [ - AudioStreamConfiguration.from_parameters(audio_stream, index) for index, audio_stream in enumerate(rospy.get_param(f'~audio_streams')) # type: ignore - ] + audio_stream_parameters = { + 'name': node.declare_parameter('audio_stream_name', '').get_parameter_value().string_value, + 'format': node.declare_parameter('audio_stream_format', '').get_parameter_value().string_value, + 'channel_count': node.declare_parameter('audio_stream_channel_count', 0).get_parameter_value().integer_value, + 'sampling_frequency': node.declare_parameter('audio_stream_sampling_frequency', 0).get_parameter_value().integer_value, + 'codec': node.declare_parameter('audio_stream_codec', '').get_parameter_value().string_value, + 'merge_channels': node.declare_parameter('audio_stream_merge_channels', True).get_parameter_value().bool_value, + 'language_code': node.declare_parameter('audio_stream_language_code', 'eng').get_parameter_value().string_value, + } + + video_streams = [VideoStreamConfiguration.from_parameters(video_stream_parameters, 0)] + audio_streams = [AudioStreamConfiguration.from_parameters(audio_stream_parameters, 0)] streams_count = len(video_streams) + len(audio_streams) if streams_count < 1: - rospy.logerr(f'At least one video or audio stream must be specified') + get_logger().error(f'At least one video or audio stream must be specified') sys.exit(os.EX_CONFIG) video_names = [video_stream.name for video_stream in video_streams] if len(duplicates := get_duplicates(video_names)) > 0: - rospy.logerr( + get_logger().error( f'Video stream names must be unique, duplicates found: {duplicates}' ) sys.exit(os.EX_CONFIG) audio_names = [audio_stream.name for audio_stream in audio_streams] if len(duplicates := get_duplicates(audio_names)) > 0: - rospy.logerr( + get_logger().error( f'Audio stream names must be unique, duplicates found: {duplicates}' ) sys.exit(os.EX_CONFIG) @@ -374,7 +401,7 @@ def from_parameters() -> 'VideoRecorderConfiguration': video_stream.language_code for video_stream in video_streams ] if len(duplicates := get_duplicates(video_lang_codes)) > 0: - rospy.logerr( + get_logger().error( f'Video language codes must be unique, duplicates found: {duplicates}' ) sys.exit(os.EX_CONFIG) @@ -383,7 +410,7 @@ def from_parameters() -> 'VideoRecorderConfiguration': audio_stream.language_code for audio_stream in audio_streams ] if len(duplicates := get_duplicates(audio_lang_codes)) > 0: - rospy.logerr( + get_logger().error( f'Audio language codes must be unique, duplicates found: {duplicates}' ) sys.exit(os.EX_CONFIG) @@ -391,13 +418,13 @@ def from_parameters() -> 'VideoRecorderConfiguration': should_exit = False for stream_name in itertools.chain(video_names, audio_names): if not VideoRecorderConfiguration._is_valid_name(stream_name): - rospy.logerr( + get_logger().error( f'Stream names must only contain alphanumeric ascii characters and underscores; invalid name: {stream_name}' ) should_exit = True for lang_code in itertools.chain(video_lang_codes, audio_lang_codes): if not VideoRecorderConfiguration._is_valid_language_code(lang_code): - rospy.logerr( + get_logger().error( 'Language codes must be ISO 639-3 codes, and should be a 3-letter code (see https://iso639-3.sil.org/code_tables/639/data)' f'; invalid language code: {lang_code}' ) @@ -414,7 +441,8 @@ def from_parameters() -> 'VideoRecorderConfiguration': class VideoRecorder: - def __init__(self, configuration: VideoRecorderConfiguration): + def __init__(self, node: rclpy.node.Node, configuration: VideoRecorderConfiguration): + self._node = node self._configuration = configuration os.makedirs(self._configuration.output_directory, exist_ok=True) @@ -434,39 +462,37 @@ def __init__(self, configuration: VideoRecorderConfiguration): self._clear_sources_lists() self._image_subscribers = { - video_stream_configuration.name: rospy.Subscriber( - video_stream_configuration.full_name, + video_stream_configuration.name: node.create_subscription( Image, - self._image_cb, - video_stream_configuration, - queue_size=10, + video_stream_configuration.full_name, + lambda msg: self._image_cb(msg, video_stream_configuration), + 10, ) for video_stream_configuration in self._configuration.video_streams } self._audio_subscribers = { - audio_stream_configuration.name: rospy.Subscriber( - audio_stream_configuration.full_name, + audio_stream_configuration.name: node.create_subscription( AudioFrame, - self._audio_cb, - audio_stream_configuration, - queue_size=10, + audio_stream_configuration.full_name, + lambda msg: self._audio_cb(msg, audio_stream_configuration), + 10, ) for audio_stream_configuration in self._configuration.audio_streams } def close(self): - apply(rospy.Subscriber.unregister, self._image_subscribers.values()) - apply(rospy.Subscriber.unregister, self._audio_subscribers.values()) + apply(self._node.destroy_subscription, self._image_subscribers.values()) + apply(self._node.destroy_subscription, self._audio_subscribers.values()) self._stop_if_started() def _image_cb(self, msg: Image, configuration: VideoStreamConfiguration): if not VideoRecorder._verify_image_msg(configuration, msg): - rospy.logerr( + get_logger().error( f'Invalid image (encoding={msg.encoding}, width={msg.width}, height={msg.height})' ) return - msg_timestamp_ns = msg.header.stamp.to_nsec() + msg_timestamp_ns = rclpy.time.Time.from_msg(msg.header.stamp).nanoseconds self._start_if_not_started(msg_timestamp_ns) if self._video_srcs[configuration.name] is None: return @@ -481,7 +507,7 @@ def _image_cb(self, msg: Image, configuration: VideoStreamConfiguration): self._last_video_frame_timestamp_ns[configuration.name] = timestamp_ns if timestamp_ns >= 0: - rospy.logdebug(f'Pushing image {msg.header.seq} for {configuration.name}') + get_logger().debug(f'Pushing image for {configuration.name}') self._video_srcs[configuration.name].emit( # type: ignore 'push-buffer', VideoRecorder.data_to_gst_buffer(msg.data, timestamp_ns, duration_ns), @@ -500,12 +526,12 @@ def _verify_image_msg(configuration: VideoStreamConfiguration, msg: Image): def _audio_cb(self, msg: AudioFrame, configuration: AudioStreamConfiguration): if not VideoRecorder._verify_audio_frame_msg(configuration, msg): - rospy.logerr( + get_logger().error( f'Invalid audio frame (format={msg.format}, channel_count={msg.channel_count}, sampling_frequency={msg.sampling_frequency})' ) return - msg_timestamp_ns = msg.header.stamp.to_nsec() + msg_timestamp_ns = rclpy.time.Time.from_msg(msg.header.stamp).nanoseconds self._start_if_not_started(msg_timestamp_ns) if self._audio_srcs[configuration.name] is None: return @@ -514,9 +540,7 @@ def _audio_cb(self, msg: AudioFrame, configuration: AudioStreamConfiguration): duration_ns = int(1 / msg.sampling_frequency * msg.frame_sample_count) if timestamp_ns >= 0: - rospy.logdebug( - f'Pushing audio frame {msg.header.seq} for {configuration.name}' - ) + get_logger().debug(f'Pushing audio frame for {configuration.name}') self._audio_srcs[configuration.name].emit( # type: ignore 'push-buffer', VideoRecorder.data_to_gst_buffer(msg.data, timestamp_ns, duration_ns), @@ -560,7 +584,7 @@ def _start_if_not_started(self, record_start_time_ns: int): + ' '.join(f'{p} ! mux.' for p in video_and_audio_pipelines) ) - rospy.loginfo(f'Launching gstreamer pipeline: {pipeline_str}') + get_logger().info(f'Launching gstreamer pipeline: {pipeline_str}') try: pipeline = Gst.parse_launch(pipeline_str) @@ -588,7 +612,7 @@ def _start_if_not_started(self, record_start_time_ns: int): self._audio_srcs = audio_srcs self._bus = bus except GLib.Error as e: # type: ignore - rospy.loginfo(f'GStreamer pipeline failed({e})') + get_logger().info(f'GStreamer pipeline failed({e})') sys.exit(-2) graph_export(self._pipeline, 'started') @@ -605,7 +629,7 @@ def _stop_if_started(self): apply(lambda s: s.emit('end-of-stream'), self._video_srcs.values()) # type: ignore apply(lambda s: s.emit('end-of-stream'), self._audio_srcs.values()) # type: ignore - rospy.loginfo('Sent EOS to all sources') + get_logger().info('Sent EOS to all sources') if self._bus: self._bus.timed_pop_filtered( # type: ignore @@ -613,7 +637,7 @@ def _stop_if_started(self): ) self._bus.remove_watch() - rospy.loginfo('Received EOS on the bus') + get_logger().info('Received EOS on the bus') self._pipeline.set_state(Gst.State.NULL) self._pipeline = None @@ -625,44 +649,44 @@ def _stop_if_started(self): def _on_bus_message_cb(self, bus, msg): def message_to_string(msg: Gst.Message) -> Tuple[str, Callable]: if msg.type == Gst.MessageType.EOS: - return 'End-of-stream', rospy.loginfo + return 'End-of-stream', get_logger().info elif msg.type == Gst.MessageType.WARNING: err, debug = msg.parse_warning() - return f'Warning: |{err}|: {debug}', rospy.logwarn + return f'Warning: |{err}|: {debug}', get_logger().warn elif msg.type == Gst.MessageType.ERROR: err, debug = msg.parse_error() - return f'Bus call: Error: |{err}|: {debug}', rospy.logerr + return f'Bus call: Error: |{err}|: {debug}', get_logger().error elif msg.type == Gst.MessageType.BUFFERING: percent = msg.parse_buffering() - return f'Buffering ({percent}%)', rospy.loginfo + return f'Buffering ({percent}%)', get_logger().info elif msg.type == Gst.MessageType.STATE_CHANGED: old_state, new_state, pending_state = msg.parse_state_changed() return ( f'Element |{msg.src.get_name()}| (of type |{type(msg.src).__name__}|) state changed from |{old_state.value_nick}| to |{new_state.value_nick}| ' f'(pending |{pending_state.value_nick}|)' - ), rospy.loginfo + ), get_logger().info elif msg.type == Gst.MessageType.STREAM_START: - return 'Stream started', rospy.loginfo + return 'Stream started', get_logger().info elif msg.type == Gst.MessageType.STREAM_STATUS: status_type, owner = msg.parse_stream_status() return ( f'Stream status; status: |{status_type.value_nick}|, owner: |{type(owner).__name__}|', - rospy.loginfo, + get_logger().info, ) elif msg.type == Gst.MessageType.LATENCY: - return 'Latency', rospy.loginfo + return 'Latency', get_logger().info elif msg.type == Gst.MessageType.NEW_CLOCK: clock = msg.parse_new_clock() return ( f'New clock; sync: |{clock.is_synced()}|, resolution: |{clock.get_resolution()}|', - rospy.loginfo, + get_logger().info, ) elif msg.type == Gst.MessageType.ASYNC_DONE: - return 'Async done', rospy.loginfo + return 'Async done', get_logger().info else: return ( f'Unknow message of type |{Gst.MessageType.get_name(msg.type).upper().replace("-", "_")}|', - rospy.loginfo, + get_logger().info, ) msg_str, log_func = message_to_string(msg) @@ -681,7 +705,7 @@ def _create_mux_pipeline(configuration: VideoRecorderConfiguration) -> str: @staticmethod def _get_filename(configuration: VideoRecorderConfiguration) -> str: - now = datetime.datetime.utcfromtimestamp(rospy.Time.now().to_sec()) + now = datetime.datetime.now() filename_us = configuration.filename_prefix + now.strftime('%Y-%m-%d_%H-%M-%S.%f') filename_ms = filename_us[:-3] return filename_ms @@ -702,7 +726,7 @@ def _create_video_pipeline(configuration: VideoStreamConfiguration) -> str: f' ! {encoder} name={encoder}_{configuration.full_name} bitrate={bitrate}' ) else: - rospy.logwarn('NVIDIA hardware encoder are not available.') + get_logger().warn('NVIDIA hardware encoder are not available.') encoder = configuration.codec.software_encoder bitrate_attribute = configuration.codec.get_software_bitrate_attribute() @@ -816,13 +840,16 @@ def _clear_last_timestamps(self) -> None: } -class VideoRecorderNode: +class VideoRecorderNode(rclpy.node.Node): def __init__(self): + super().__init__(NODE_NAME) + self._recorder_lock = threading.Lock() self._recorder = None - self._recorder_configuration = VideoRecorderConfiguration.from_parameters() + self._recorder_configuration = VideoRecorderConfiguration.from_parameters(self) self._filter_state = hbba_lite.OnOffHbbaFilterState( # type: ignore + self, 'video_recorder/filter_state' ) self._filter_state.on_changed(self._on_filter_state_changed) @@ -833,12 +860,12 @@ def _on_filter_state_changed(self, _, next_is_filtering_all_messages): self._recorder.close() self._recorder = None elif not next_is_filtering_all_messages and self._recorder is None: - self._recorder = VideoRecorder(self._recorder_configuration) + self._recorder = VideoRecorder(self, self._recorder_configuration) def run(self): try: - rospy.spin() - except rospy.ROSInterruptException: + rclpy.spin(self) + except KeyboardInterrupt: pass finally: with self._recorder_lock: @@ -848,16 +875,21 @@ def run(self): def main(): - rospy.init_node('video_recorder_node') + rclpy.init() Gst.init(None) video_recorder_node = VideoRecorderNode() - video_recorder_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + video_recorder_node.run() + except KeyboardInterrupt: pass + finally: + video_recorder_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/utils/recorders/src/perception_logger_node.cpp b/ros/utils/recorders/src/perception_logger_node.cpp index 8688b363..2119b8ee 100644 --- a/ros/utils/recorders/src/perception_logger_node.cpp +++ b/ros/utils/recorders/src/perception_logger_node.cpp @@ -3,14 +3,17 @@ #include #include -#include -#include - -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include #include #include @@ -41,74 +44,87 @@ struct PerceptionLoggerNodeConfiguration string frameId; }; -class PerceptionLoggerNode +class PerceptionLoggerNode : public rclcpp::Node { - ros::NodeHandle& m_nodeHandle; - PerceptionLoggerNodeConfiguration m_configuration; + string m_databasePath; + string m_frameId; - SQLite::Database m_database; + unique_ptr m_database; unique_ptr m_videoAnalysisLogger; unique_ptr m_audioAnalysisLogger; unique_ptr m_speechLogger; unique_ptr m_hbbaStrategyStateLogger; - tf::TransformListener m_listener; + unique_ptr m_tfBuffer; + shared_ptr m_tfListener; - ros::Subscriber m_videoAnalysis3dSubscriber; - ros::Subscriber m_audioAnalysisSubscriber; - ros::Subscriber m_talkTextSubscriber; - ros::Subscriber m_speechToTextTranscriptSubscriber; - ros::Subscriber m_hbbaStrategyStateSubscriber; + rclcpp::Subscription::SharedPtr m_videoAnalysis3dSubscriber; + rclcpp::Subscription::SharedPtr m_audioAnalysisSubscriber; + rclcpp::Subscription::SharedPtr m_talkTextSubscriber; + rclcpp::Subscription::SharedPtr m_speechToTextTranscriptSubscriber; + rclcpp::Subscription::SharedPtr m_hbbaStrategyStateSubscriber; public: - PerceptionLoggerNode(ros::NodeHandle& nodeHandle, PerceptionLoggerNodeConfiguration configuration) - : m_nodeHandle(nodeHandle), - m_configuration(move(configuration)), - m_database(m_configuration.databasePath, SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE) + PerceptionLoggerNode() : rclcpp::Node("perception_logger_node") { - m_videoAnalysisLogger = make_unique(m_database); - m_audioAnalysisLogger = make_unique(m_database); - m_speechLogger = make_unique(m_database); - m_hbbaStrategyStateLogger = make_unique(m_database); - - m_videoAnalysis3dSubscriber = - m_nodeHandle.subscribe("video_analysis", 10, &PerceptionLoggerNode::videoAnalysisSubscriberCallback, this); - m_audioAnalysisSubscriber = - m_nodeHandle.subscribe("audio_analysis", 10, &PerceptionLoggerNode::audioAnalysisSubscriberCallback, this); - m_talkTextSubscriber = - m_nodeHandle.subscribe("talk/text", 10, &PerceptionLoggerNode::talkTextSubscriberCallback, this); - m_speechToTextTranscriptSubscriber = m_nodeHandle.subscribe( + m_databasePath = declare_parameter("database_path", ""); + m_frameId = declare_parameter("frame_id", ""); + + m_database = std::make_unique(m_databasePath, SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE); + + m_videoAnalysisLogger = std::make_unique(*m_database); + m_audioAnalysisLogger = std::make_unique(*m_database); + m_speechLogger = std::make_unique(*m_database); + m_hbbaStrategyStateLogger = std::make_unique(*m_database); + + m_videoAnalysis3dSubscriber = create_subscription( + "video_analysis", + 10, + [this](const perception_msgs::msg::VideoAnalysis::SharedPtr msg) { videoAnalysisSubscriberCallback(msg); }); + m_audioAnalysisSubscriber = create_subscription( + "audio_analysis", + 10, + [this](const perception_msgs::msg::AudioAnalysis::SharedPtr msg) { audioAnalysisSubscriberCallback(msg); }); + m_talkTextSubscriber = create_subscription( + "talk/text", + 10, + [this](const behavior_msgs::msg::Text::SharedPtr msg) { talkTextSubscriberCallback(msg); }); + m_speechToTextTranscriptSubscriber = create_subscription( "speech_to_text/transcript", 10, - &PerceptionLoggerNode::speechToTextTranscriptSubscriberCallback, - this); - m_hbbaStrategyStateSubscriber = m_nodeHandle.subscribe( + [this](const perception_msgs::msg::Transcript::SharedPtr msg) + { speechToTextTranscriptSubscriberCallback(msg); }); + m_hbbaStrategyStateSubscriber = create_subscription( "hbba_strategy_state_log", 10, - &PerceptionLoggerNode::hbbaStrategyStateSubscriberCallback, - this); + [this](const hbba_lite_msgs::msg::StrategyState::SharedPtr msg) { hbbaStrategyStateSubscriberCallback(msg); }); + + m_tfBuffer = std::make_unique(get_clock()); + m_tfListener = std::make_shared(*m_tfBuffer); } virtual ~PerceptionLoggerNode() {} - void videoAnalysisSubscriberCallback(const video_analyzer::VideoAnalysis::ConstPtr& msg) + void videoAnalysisSubscriberCallback(const perception_msgs::msg::VideoAnalysis::SharedPtr msg) { if (!msg->contains_3d_positions) { - ROS_ERROR("The video analysis must contain 3d positions."); + RCLCPP_ERROR(get_logger(), "The video analysis must contain 3d positions."); return; } - tf::StampedTransform transform; + geometry_msgs::msg::TransformStamped transformMsg; try { - m_listener.lookupTransform(m_configuration.frameId, msg->header.frame_id, msg->header.stamp, transform); + transformMsg = m_tfBuffer->lookupTransform(m_frameId, msg->header.frame_id, msg->header.stamp); } - catch (tf::TransformException ex) + catch (tf2::TransformException& ex) { - ROS_ERROR("%s", ex.what()); + RCLCPP_ERROR(get_logger(), "%s", ex.what()); return; } + tf2::Stamped transform; + tf2::convert(transformMsg, transform); for (auto& object : msg->objects) { @@ -116,12 +132,13 @@ class PerceptionLoggerNode } } - void audioAnalysisSubscriberCallback(const audio_analyzer::AudioAnalysis::ConstPtr& msg) + void audioAnalysisSubscriberCallback(const perception_msgs::msg::AudioAnalysis::SharedPtr msg) { - if (msg->header.frame_id != m_configuration.frameId) + if (msg->header.frame_id != m_frameId) { - ROS_ERROR_STREAM( - "Invalid direction frame id (" << msg->header.frame_id << " ! = " << m_configuration.frameId); + RCLCPP_ERROR_STREAM( + get_logger(), + "Invalid direction frame id (" << msg->header.frame_id << " ! = " << m_frameId); return; } if (msg->audio_classes.empty()) @@ -132,40 +149,42 @@ class PerceptionLoggerNode m_audioAnalysisLogger->log(msgToAnalysis(msg)); } - void talkTextSubscriberCallback(const talk::Text::ConstPtr& msg) + void talkTextSubscriberCallback(const behavior_msgs::msg::Text::SharedPtr msg) { - m_speechLogger->log(Speech(ros::Time::now(), SpeechSource::ROBOT, msg->text)); + m_speechLogger->log(Speech(get_clock()->now(), SpeechSource::ROBOT, msg->text)); } - void speechToTextTranscriptSubscriberCallback(const speech_to_text::Transcript::ConstPtr& msg) + void speechToTextTranscriptSubscriberCallback(const perception_msgs::msg::Transcript::SharedPtr msg) { if (msg->is_final) { - m_speechLogger->log(Speech(ros::Time::now(), SpeechSource::HUMAN, msg->text)); + m_speechLogger->log(Speech(get_clock()->now(), SpeechSource::HUMAN, msg->text)); } } - void hbbaStrategyStateSubscriberCallback(const hbba_lite::StrategyState::ConstPtr& msg) + void hbbaStrategyStateSubscriberCallback(const hbba_lite_msgs::msg::StrategyState::SharedPtr msg) { m_hbbaStrategyStateLogger->log( - HbbaStrategyState(ros::Time::now(), msg->desire_type_name, msg->strategy_type_name, msg->enabled)); + HbbaStrategyState(get_clock()->now(), msg->desire_type_name, msg->strategy_type_name, msg->enabled)); } - void run() { ros::spin(); } + void run() { rclcpp::spin(shared_from_this()); } private: - static Position pointToPosition(const geometry_msgs::Point& point, const tf::StampedTransform& transform) + static Position + pointToPosition(const geometry_msgs::msg::Point& point, const tf2::Stamped& transform) { - tf::Point transformedPoint = transform * tf::Point(point.x, point.y, point.z); + tf2::Vector3 transformedPoint = transform * tf2::Vector3(point.x, point.y, point.z); return Position{transformedPoint.x(), transformedPoint.y(), transformedPoint.z()}; } - static ImagePosition pointToImagePosition(const geometry_msgs::Point& point) + static ImagePosition pointToImagePosition(const geometry_msgs::msg::Point& point) { return ImagePosition{point.x, point.y}; } - static BoundingBox centreWidthHeightToBoundingBox(const geometry_msgs::Point& centre, double width, double height) + static BoundingBox + centreWidthHeightToBoundingBox(const geometry_msgs::msg::Point& centre, double width, double height) { return BoundingBox{pointToImagePosition(centre), width, height}; } @@ -177,9 +196,9 @@ class PerceptionLoggerNode } static VideoAnalysis msgToAnalysis( - const video_analyzer::VideoAnalysisObject& msg, - const ros::Time& timestamp, - const tf::StampedTransform& transform) + const perception_msgs::msg::VideoAnalysisObject& msg, + const rclcpp::Time& timestamp, + const tf2::Stamped& transform) { Position position = pointToPosition(msg.center_3d, transform); VideoAnalysis videoAnalysis{ @@ -209,7 +228,7 @@ class PerceptionLoggerNode std::begin(msg.person_pose_3d), std::end(msg.person_pose_3d), std::back_inserter(videoAnalysis.personPose.value()), - [&transform](const geometry_msgs::Point& point) { return pointToPosition(point, transform); }); + [&transform](const geometry_msgs::msg::Point& point) { return pointToPosition(point, transform); }); } if (!msg.person_pose_confidence.empty()) { @@ -225,10 +244,10 @@ class PerceptionLoggerNode return videoAnalysis; } - static AudioAnalysis msgToAnalysis(const audio_analyzer::AudioAnalysis::ConstPtr& msg) + static AudioAnalysis msgToAnalysis(const perception_msgs::msg::AudioAnalysis::SharedPtr msg) { AudioAnalysis audioAnalysis( - msg->header.stamp, + rclcpp::Time(msg->header.stamp), Direction{msg->direction_x, msg->direction_y, msg->direction_z}, msg->tracking_id, mergeClasses(msg->audio_classes)); @@ -244,26 +263,12 @@ class PerceptionLoggerNode int main(int argc, char** argv) { - ros::init(argc, argv, "perception_logger_node"); - - ros::NodeHandle nodeHandle; - ros::NodeHandle privateNodeHandle("~"); + rclcpp::init(argc, argv); - PerceptionLoggerNodeConfiguration configuration; - - if (!privateNodeHandle.getParam("database_path", configuration.databasePath)) - { - ROS_ERROR("The parameter database_path is required."); - return -1; - } - if (!privateNodeHandle.getParam("frame_id", configuration.frameId)) - { - ROS_ERROR("The parameter frame_id is required."); - return -1; - } + auto node = make_shared(); + node->run(); - PerceptionLoggerNode node(nodeHandle, configuration); - node.run(); + rclcpp::shutdown(); return 0; } diff --git a/ros/utils/recorders/test/perception_logger/PerceptionLoggerTests.cpp b/ros/utils/recorders/test/perception_logger/PerceptionLoggerTests.cpp index 1c6cbcd6..104eab34 100644 --- a/ros/utils/recorders/test/perception_logger/PerceptionLoggerTests.cpp +++ b/ros/utils/recorders/test/perception_logger/PerceptionLoggerTests.cpp @@ -120,6 +120,6 @@ TEST(PerceptionLoggerTests, timestamp_constructor_shouldSetAttributes) Timestamp t0(5); EXPECT_EQ(t0.unixEpochMs, 5); - Timestamp t1(ros::Time(5.2)); + Timestamp t1(rclcpp::Time(static_cast(5.2 * 1e9))); EXPECT_EQ(t1.unixEpochMs, 5200); } diff --git a/ros/utils/recorders/test/perception_logger/sqlite/SQLiteVideoAnalysisLoggerTests.cpp b/ros/utils/recorders/test/perception_logger/sqlite/SQLiteVideoAnalysisLoggerTests.cpp index b28273e2..32667bb7 100644 --- a/ros/utils/recorders/test/perception_logger/sqlite/SQLiteVideoAnalysisLoggerTests.cpp +++ b/ros/utils/recorders/test/perception_logger/sqlite/SQLiteVideoAnalysisLoggerTests.cpp @@ -4,7 +4,7 @@ #include -#include "comparisons.h" +#include "../comparisons.h" using namespace std; diff --git a/ros/utils/t_top_hbba_lite/CMakeLists.txt b/ros/utils/t_top_hbba_lite/CMakeLists.txt index 1a6f1d39..2bff28e8 100644 --- a/ros/utils/t_top_hbba_lite/CMakeLists.txt +++ b/ros/utils/t_top_hbba_lite/CMakeLists.txt @@ -1,221 +1,70 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(t_top_hbba_lite) -## Compile as C++11, supported in ROS Kinetic and newer -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - geometry_msgs - hbba_lite - nav_msgs - sensor_msgs - sound_player - std_msgs - talk - tf - gesture - led_animations - daemon_ros_client +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +set(MUSIC_BEAT_DETECTOR_ENABLE_TESTS OFF CACHE BOOL "") + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclcpp REQUIRED) +find_package(geometry_msgs REQUIRED) +find_package(hbba_lite REQUIRED) +find_package(nav_msgs REQUIRED) +find_package(sensor_msgs REQUIRED) +find_package(behavior_msgs REQUIRED) +find_package(perception_msgs REQUIRED) +find_package(std_msgs REQUIRED) +find_package(tf2 REQUIRED) +find_package(daemon_ros_client REQUIRED) + +# C++ Libraries +add_library(t_top_hbba_lite_cpp + src/Desires.cpp + src/Strategies.cpp ) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -# add_message_files( -# FILES -# Message1.msg -# Message2.msg -# ) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -# generate_messages( -# DEPENDENCIES -# geometry_msgs# nav_msgs# sensor_msgs# std_msgs -# ) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( - INCLUDE_DIRS include - LIBRARIES t_top_hbba_lite - CATKIN_DEPENDS hbba_lite sound_player talk tf gesture - # DEPENDS system_lib +target_include_directories(t_top_hbba_lite_cpp + PUBLIC + $ + $ ) - -########### -## Build ## -########### - -## Specify additional locations of header files -## Your package locations should be listed before other locations -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( - include - ${catkin_INCLUDE_DIRS} +ament_target_dependencies(t_top_hbba_lite_cpp rclcpp hbba_lite nav_msgs sensor_msgs behavior_msgs std_msgs std_msgs daemon_ros_client) + +ament_export_dependencies(rclcpp hbba_lite nav_msgs sensor_msgs behavior_msgs std_msgs std_msgs daemon_ros_client) +ament_export_targets(export_t_top_hbba_lite_cpp HAS_LIBRARY_TARGET) + +install( + TARGETS t_top_hbba_lite_cpp + EXPORT export_t_top_hbba_lite_cpp + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + RUNTIME DESTINATION bin + INCLUDES DESTINATION include ) -## Declare a C++ library -add_library(${PROJECT_NAME} - src/Desires.cpp - src/Strategies.cpp - ) - -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) +install( + DIRECTORY include/ + DESTINATION include +) -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide +# C++ Nodes add_executable(set_head_pose_arbitration_node src/set_head_pose_arbitration_node.cpp) +ament_target_dependencies(set_head_pose_arbitration_node rclcpp geometry_msgs daemon_ros_client tf2) +install(TARGETS set_head_pose_arbitration_node DESTINATION lib/${PROJECT_NAME}) -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -target_link_libraries(${PROJECT_NAME} - ${catkin_LIBRARIES} - ) -target_link_libraries(set_head_pose_arbitration_node - ${catkin_LIBRARIES} - ) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -# catkin_install_python(PROGRAMS -# scripts/my_python_script -# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_t_top_hbba_lite.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() +ament_export_dependencies(rclcpp geometry_msgs daemon_ros_client tf2) -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/utils/t_top_hbba_lite/README.md b/ros/utils/t_top_hbba_lite/README.md index f3f9232e..9a70ab5b 100644 --- a/ros/utils/t_top_hbba_lite/README.md +++ b/ros/utils/t_top_hbba_lite/README.md @@ -8,10 +8,11 @@ This node applies priority arbitration to the head pose topic. #### Parameters -- `topics`: The topic descriptions containing the topic name (string), priority (int, lower means higher priority) and timeout_s value (double). +- `topics` (string): The topic names. +- `priorities` (int): The priority for each topic (int, lower means higher priority). +- `timeout_s` (double): The timeout in seconds for each topic. - `offset_topics` (array of string): The topic names that apply an offset to the head position -- `latch` (bool): Indicates if the output topic is latched. #### Published Topics -- `daemon/set_head_pose` ([geometry_msgs/PoseStamped](http://docs.ros.org/en/noetic/api/geometry_msgs/html/msg/PoseStamped.html)): The output topic. +- `daemon/set_head_pose` ([geometry_msgs/PoseStamped](https://docs.ros.org/en/humble/p/geometry_msgs/interfaces/msg/PoseStamped.html)): The output topic. diff --git a/ros/utils/t_top_hbba_lite/include/t_top_hbba_lite/Desires.h b/ros/utils/t_top_hbba_lite/include/t_top_hbba_lite/Desires.h index bea0ee29..5e24632e 100644 --- a/ros/utils/t_top_hbba_lite/include/t_top_hbba_lite/Desires.h +++ b/ros/utils/t_top_hbba_lite/include/t_top_hbba_lite/Desires.h @@ -4,7 +4,7 @@ #include #include -#include +#include #include #include @@ -199,7 +199,7 @@ class LedAnimationDesire : public Desire std::string m_name; double m_durationS; double m_speed; - std::vector m_colors; + std::vector m_colors; public: /** @@ -207,7 +207,7 @@ class LedAnimationDesire : public Desire */ explicit LedAnimationDesire( std::string name, - std::vector colors = {}, + std::vector colors = {}, double speed = 1.0, double durationS = std::numeric_limits::infinity(), uint16_t intensity = 1); @@ -218,7 +218,7 @@ class LedAnimationDesire : public Desire const std::string& name() const; double durationS() const; double speed() const; - const std::vector& colors() const; + const std::vector& colors() const; }; inline const std::string& LedAnimationDesire::name() const @@ -236,7 +236,7 @@ inline double LedAnimationDesire::speed() const return m_speed; } -inline const std::vector& LedAnimationDesire::colors() const +inline const std::vector& LedAnimationDesire::colors() const { return m_colors; } diff --git a/ros/utils/t_top_hbba_lite/include/t_top_hbba_lite/Strategies.h b/ros/utils/t_top_hbba_lite/include/t_top_hbba_lite/Strategies.h index fc28badf..4b3fcd36 100644 --- a/ros/utils/t_top_hbba_lite/include/t_top_hbba_lite/Strategies.h +++ b/ros/utils/t_top_hbba_lite/include/t_top_hbba_lite/Strategies.h @@ -3,24 +3,27 @@ #include -#include +#include #include -#include -#include -#include -#include +#include + +#include +#include +#include +#include +#include #include class FaceAnimationStrategy : public Strategy { - ros::NodeHandle& m_nodeHandle; - ros::Publisher m_animationPublisher; + std::shared_ptr m_node; + rclcpp::Publisher::SharedPtr m_animationPublisher; public: - FaceAnimationStrategy(uint16_t utility, std::shared_ptr filterPool, ros::NodeHandle& nodeHandle); + FaceAnimationStrategy(uint16_t utility, std::shared_ptr filterPool, std::shared_ptr node); DECLARE_NOT_COPYABLE(FaceAnimationStrategy); DECLARE_NOT_MOVABLE(FaceAnimationStrategy); @@ -34,11 +37,11 @@ class FaceAnimationStrategy : public Strategy class LedEmotionStrategy : public Strategy { - ros::NodeHandle& m_nodeHandle; - ros::Publisher m_emotionPublisher; + std::shared_ptr m_node; + rclcpp::Publisher::SharedPtr m_emotionPublisher; public: - LedEmotionStrategy(uint16_t utility, std::shared_ptr filterPool, ros::NodeHandle& nodeHandle); + LedEmotionStrategy(uint16_t utility, std::shared_ptr filterPool, std::shared_ptr node); DECLARE_NOT_COPYABLE(LedEmotionStrategy); DECLARE_NOT_MOVABLE(LedEmotionStrategy); @@ -52,16 +55,16 @@ class LedEmotionStrategy : public Strategy class LedAnimationStrategy : public Strategy { std::shared_ptr m_desireSet; - ros::NodeHandle& m_nodeHandle; - ros::Publisher m_animationPublisher; - ros::Subscriber m_animationDoneSubscriber; + std::shared_ptr m_node; + rclcpp::Publisher::SharedPtr m_animationPublisher; + rclcpp::Subscription::SharedPtr m_animationDoneSubscriber; public: LedAnimationStrategy( uint16_t utility, std::shared_ptr filterPool, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle); + std::shared_ptr node); DECLARE_NOT_COPYABLE(LedAnimationStrategy); DECLARE_NOT_MOVABLE(LedAnimationStrategy); @@ -72,19 +75,19 @@ class LedAnimationStrategy : public Strategy void onEnabling(const LedAnimationDesire& desire) override; private: - void animationDoneSubscriberCallback(const led_animations::Done::ConstPtr& msg); + void animationDoneSubscriberCallback(const behavior_msgs::msg::Done::SharedPtr msg); }; class SpecificFaceFollowingStrategy : public Strategy { - ros::NodeHandle& m_nodeHandle; - ros::Publisher m_targetNamePublisher; + std::shared_ptr m_node; + rclcpp::Publisher::SharedPtr m_targetNamePublisher; public: SpecificFaceFollowingStrategy( uint16_t utility, std::shared_ptr filterPool, - ros::NodeHandle& nodeHandle); + std::shared_ptr node); DECLARE_NOT_COPYABLE(SpecificFaceFollowingStrategy); DECLARE_NOT_MOVABLE(SpecificFaceFollowingStrategy); @@ -98,16 +101,16 @@ class SpecificFaceFollowingStrategy : public Strategy { std::shared_ptr m_desireSet; - ros::NodeHandle& m_nodeHandle; - ros::Publisher m_talkPublisher; - ros::Subscriber m_talkDoneSubscriber; + std::shared_ptr m_node; + rclcpp::Publisher::SharedPtr m_talkPublisher; + rclcpp::Subscription::SharedPtr m_talkDoneSubscriber; public: TalkStrategy( uint16_t utility, std::shared_ptr filterPool, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle); + std::shared_ptr node); DECLARE_NOT_COPYABLE(TalkStrategy); DECLARE_NOT_MOVABLE(TalkStrategy); @@ -118,22 +121,22 @@ class TalkStrategy : public Strategy void onEnabling(const TalkDesire& desire) override; private: - void talkDoneSubscriberCallback(const talk::Done::ConstPtr& msg); + void talkDoneSubscriberCallback(const behavior_msgs::msg::Done::SharedPtr msg); }; class GestureStrategy : public Strategy { std::shared_ptr m_desireSet; - ros::NodeHandle& m_nodeHandle; - ros::Publisher m_gesturePublisher; - ros::Subscriber m_gestureDoneSubscriber; + std::shared_ptr m_node; + rclcpp::Publisher::SharedPtr m_gesturePublisher; + rclcpp::Subscription::SharedPtr m_gestureDoneSubscriber; public: GestureStrategy( uint16_t utility, std::shared_ptr filterPool, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle); + std::shared_ptr node); DECLARE_NOT_COPYABLE(GestureStrategy); DECLARE_NOT_MOVABLE(GestureStrategy); @@ -144,22 +147,22 @@ class GestureStrategy : public Strategy void onEnabling(const GestureDesire& desire) override; private: - void gestureDoneSubscriberCallback(const gesture::Done::ConstPtr& msg); + void gestureDoneSubscriberCallback(const behavior_msgs::msg::Done::SharedPtr msg); }; class PlaySoundStrategy : public Strategy { std::shared_ptr m_desireSet; - ros::NodeHandle& m_nodeHandle; - ros::Publisher m_pathPublisher; - ros::Subscriber m_soundDoneSubscriber; + std::shared_ptr m_node; + rclcpp::Publisher::SharedPtr m_pathPublisher; + rclcpp::Subscription::SharedPtr m_soundDoneSubscriber; public: PlaySoundStrategy( uint16_t utility, std::shared_ptr filterPool, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle); + std::shared_ptr node); DECLARE_NOT_COPYABLE(PlaySoundStrategy); DECLARE_NOT_MOVABLE(PlaySoundStrategy); @@ -170,7 +173,7 @@ class PlaySoundStrategy : public Strategy void onEnabling(const PlaySoundDesire& desire) override; private: - void soundDoneSubscriberCallback(const sound_player::Done::ConstPtr& msg); + void soundDoneSubscriberCallback(const behavior_msgs::msg::Done::SharedPtr msg); }; std::unique_ptr @@ -202,14 +205,16 @@ std::unique_ptr createSpeechToTextStrategy(std::shared_ptr createExploreStrategy(std::shared_ptr filterPool, uint16_t utility = 1); std::unique_ptr createFaceAnimationStrategy( std::shared_ptr filterPool, - ros::NodeHandle& nodeHandle, + std::shared_ptr node, + uint16_t utility = 1); +std::unique_ptr createLedEmotionStrategy( + std::shared_ptr filterPool, + std::shared_ptr node, uint16_t utility = 1); -std::unique_ptr - createLedEmotionStrategy(std::shared_ptr filterPool, ros::NodeHandle& nodeHandle, uint16_t utility = 1); std::unique_ptr createLedAnimationStrategy( std::shared_ptr filterPool, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + std::shared_ptr node, uint16_t utility = 1); std::unique_ptr createSoundFollowingStrategy(std::shared_ptr filterPool, uint16_t utility = 1); @@ -217,31 +222,32 @@ std::unique_ptr createNearestFaceFollowingStrategy(std::shared_ptr filterPool, uint16_t utility = 1); std::unique_ptr createSpecificFaceFollowingStrategy( std::shared_ptr filterPool, - ros::NodeHandle& nodeHandle, + std::shared_ptr node, uint16_t utility = 1); std::unique_ptr createSoundObjectPersonFollowingStrategy(std::shared_ptr filterPool, uint16_t utility = 1); std::unique_ptr createTalkStrategy( std::shared_ptr filterPool, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + std::shared_ptr node, uint16_t utility = 1); std::unique_ptr createGestureStrategy( std::shared_ptr filterPool, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + std::shared_ptr node, uint16_t utility = 1); std::unique_ptr createDanceStrategy(std::shared_ptr filterPool, uint16_t utility = 1); std::unique_ptr createPlaySoundStrategy( std::shared_ptr filterPool, std::shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + std::shared_ptr node, uint16_t utility = 1); std::unique_ptr createTelepresenceStrategy(std::shared_ptr filterPool, uint16_t utility = 1); std::unique_ptr createTeleoperationStrategy(std::shared_ptr filterPool, uint16_t utility = 1); -std::unique_ptr createTooCloseReactionStrategy(std::shared_ptr filterPool, uint16_t utility = 1); +std::unique_ptr + createTooCloseReactionStrategy(std::shared_ptr filterPool, uint16_t utility = 1); #endif diff --git a/ros/utils/t_top_hbba_lite/package.xml b/ros/utils/t_top_hbba_lite/package.xml index a0740f97..a2fe007d 100644 --- a/ros/utils/t_top_hbba_lite/package.xml +++ b/ros/utils/t_top_hbba_lite/package.xml @@ -1,92 +1,32 @@ - + + t_top_hbba_lite 0.0.0 The t_top_hbba_lite package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rclcpp + geometry_msgs + hbba_lite + nav_msgs + sensor_msgs + behavior_msgs + perception_msgs + std_msgs + tf2 + daemon_ros_client - - - - TODO + rosidl_default_runtime + rosidl_interface_packages + ament_lint_auto + ament_lint_common - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - geometry_msgs - hbba_lite - nav_msgs - sensor_msgs - sound_player - std_msgs - talk - tf - gesture - led_animations - daemon_ros_client - geometry_msgs - hbba_lite - nav_msgs - sensor_msgs - sound_player - std_msgs - talk - tf - gesture - led_animations - daemon_ros_client - geometry_msgs - hbba_lite - nav_msgs - sensor_msgs - sound_player - std_msgs - talk - tf - gesture - led_animations - daemon_ros_client - - - - - + ament_cmake diff --git a/ros/utils/t_top_hbba_lite/src/Desires.cpp b/ros/utils/t_top_hbba_lite/src/Desires.cpp index b326e4c3..d0db970f 100644 --- a/ros/utils/t_top_hbba_lite/src/Desires.cpp +++ b/ros/utils/t_top_hbba_lite/src/Desires.cpp @@ -43,7 +43,7 @@ LedEmotionDesire::LedEmotionDesire(string name, uint16_t intensity) : Desire(int LedAnimationDesire::LedAnimationDesire( string name, - vector colors, + vector colors, double speed, double durationS, uint16_t intensity) diff --git a/ros/utils/t_top_hbba_lite/src/Strategies.cpp b/ros/utils/t_top_hbba_lite/src/Strategies.cpp index 47c96b5b..f0a84e6b 100644 --- a/ros/utils/t_top_hbba_lite/src/Strategies.cpp +++ b/ros/utils/t_top_hbba_lite/src/Strategies.cpp @@ -1,21 +1,16 @@ #include -#include -#include -#include -#include -#include - using namespace std; FaceAnimationStrategy::FaceAnimationStrategy( uint16_t utility, shared_ptr filterPool, - ros::NodeHandle& nodeHandle) + shared_ptr node) : Strategy(utility, {}, {}, move(filterPool)), - m_nodeHandle(nodeHandle) + m_node(move(node)) { - m_animationPublisher = nodeHandle.advertise("face/animation", 1, true); + m_animationPublisher = + m_node->create_publisher("face/animation", rclcpp::QoS(1).transient_local()); } StrategyType FaceAnimationStrategy::strategyType() @@ -25,29 +20,33 @@ StrategyType FaceAnimationStrategy::strategyType() void FaceAnimationStrategy::onEnabling(const FaceAnimationDesire& desire) { - std_msgs::String msg; + std_msgs::msg::String msg; msg.data = desire.name(); - m_animationPublisher.publish(msg); + m_animationPublisher->publish(msg); } void FaceAnimationStrategy::onDisabling() { - std_msgs::String msg; + std_msgs::msg::String msg; msg.data = "normal"; - m_animationPublisher.publish(msg); + m_animationPublisher->publish(msg); Strategy::onDisabling(); } -LedEmotionStrategy::LedEmotionStrategy(uint16_t utility, shared_ptr filterPool, ros::NodeHandle& nodeHandle) +LedEmotionStrategy::LedEmotionStrategy( + uint16_t utility, + shared_ptr filterPool, + shared_ptr node) : Strategy( utility, {}, {{"led_emotions/filter_state", FilterConfiguration::onOff()}}, move(filterPool)), - m_nodeHandle(nodeHandle) + m_node(move(node)) { - m_emotionPublisher = nodeHandle.advertise("led_emotions/name", 1, true); + m_emotionPublisher = + m_node->create_publisher("led_emotions/name", rclcpp::QoS(1).transient_local()); } StrategyType LedEmotionStrategy::strategyType() @@ -57,27 +56,31 @@ StrategyType LedEmotionStrategy::strategyType() void LedEmotionStrategy::onEnabling(const LedEmotionDesire& desire) { - std_msgs::String msg; + std_msgs::msg::String msg; msg.data = desire.name(); - m_emotionPublisher.publish(msg); + m_emotionPublisher->publish(msg); } LedAnimationStrategy::LedAnimationStrategy( uint16_t utility, shared_ptr filterPool, shared_ptr desireSet, - ros::NodeHandle& nodeHandle) + shared_ptr node) : Strategy( utility, {}, {{"led_animations/filter_state", FilterConfiguration::onOff()}}, move(filterPool)), m_desireSet(desireSet), - m_nodeHandle(nodeHandle) + m_node(move(node)) { - m_animationPublisher = nodeHandle.advertise("led_animations/animation", 1, true); - m_animationDoneSubscriber = - nodeHandle.subscribe("led_animations/done", 1, &LedAnimationStrategy::animationDoneSubscriberCallback, this); + m_animationPublisher = m_node->create_publisher( + "led_animations/animation", + rclcpp::QoS(1).transient_local()); + m_animationDoneSubscriber = m_node->create_subscription( + "led_animations/done", + 1, + [this](const behavior_msgs::msg::Done::SharedPtr msg) { animationDoneSubscriberCallback(msg); }); } StrategyType LedAnimationStrategy::strategyType() @@ -87,16 +90,16 @@ StrategyType LedAnimationStrategy::strategyType() void LedAnimationStrategy::onEnabling(const LedAnimationDesire& desire) { - led_animations::Animation msg; + behavior_msgs::msg::LedAnimation msg; msg.id = desire.id(); msg.duration_s = desire.durationS(); msg.name = desire.name(); msg.speed = desire.speed(); msg.colors = desire.colors(); - m_animationPublisher.publish(msg); + m_animationPublisher->publish(msg); } -void LedAnimationStrategy::animationDoneSubscriberCallback(const led_animations::Done::ConstPtr& msg) +void LedAnimationStrategy::animationDoneSubscriberCallback(const behavior_msgs::msg::Done::SharedPtr msg) { if (msg->id == desireId()) { @@ -107,16 +110,17 @@ void LedAnimationStrategy::animationDoneSubscriberCallback(const led_animations: SpecificFaceFollowingStrategy::SpecificFaceFollowingStrategy( uint16_t utility, shared_ptr filterPool, - ros::NodeHandle& nodeHandle) + shared_ptr node) : Strategy( utility, {}, {{"video_analyzer_3d/image_raw/filter_state", FilterConfiguration::throttling(3)}, {"specific_face_following/filter_state", FilterConfiguration::onOff()}}, move(filterPool)), - m_nodeHandle(nodeHandle) + m_node(move(node)) { - m_targetNamePublisher = nodeHandle.advertise("face_following/target_name", 1, true); + m_targetNamePublisher = + m_node->create_publisher("face_following/target_name", rclcpp::QoS(1).transient_local()); } StrategyType SpecificFaceFollowingStrategy::strategyType() @@ -126,26 +130,29 @@ StrategyType SpecificFaceFollowingStrategy::strategyType() void SpecificFaceFollowingStrategy::onEnabling(const SpecificFaceFollowingDesire& desire) { - std_msgs::String msg; + std_msgs::msg::String msg; msg.data = desire.targetName(); - m_targetNamePublisher.publish(msg); + m_targetNamePublisher->publish(msg); } TalkStrategy::TalkStrategy( uint16_t utility, shared_ptr filterPool, shared_ptr desireSet, - ros::NodeHandle& nodeHandle) + shared_ptr node) : Strategy( utility, {{"sound", 1}}, {{"talk/filter_state", FilterConfiguration::onOff()}}, move(filterPool)), m_desireSet(move(desireSet)), - m_nodeHandle(nodeHandle) + m_node(move(node)) { - m_talkPublisher = nodeHandle.advertise("talk/text", 1, true); - m_talkDoneSubscriber = nodeHandle.subscribe("talk/done", 10, &TalkStrategy::talkDoneSubscriberCallback, this); + m_talkPublisher = m_node->create_publisher("talk/text", rclcpp::QoS(1).transient_local()); + m_talkDoneSubscriber = m_node->create_subscription( + "talk/done", + 1, + [this](const behavior_msgs::msg::Done::SharedPtr msg) { talkDoneSubscriberCallback(msg); }); } StrategyType TalkStrategy::strategyType() @@ -155,13 +162,13 @@ StrategyType TalkStrategy::strategyType() void TalkStrategy::onEnabling(const TalkDesire& desire) { - talk::Text msg; + behavior_msgs::msg::Text msg; msg.text = desire.text(); msg.id = desire.id(); - m_talkPublisher.publish(msg); + m_talkPublisher->publish(msg); } -void TalkStrategy::talkDoneSubscriberCallback(const talk::Done::ConstPtr& msg) +void TalkStrategy::talkDoneSubscriberCallback(const behavior_msgs::msg::Done::SharedPtr msg) { if (msg->id == desireId()) { @@ -173,14 +180,17 @@ GestureStrategy::GestureStrategy( uint16_t utility, shared_ptr filterPool, shared_ptr desireSet, - ros::NodeHandle& nodeHandle) + shared_ptr node) : Strategy(utility, {}, {{"gesture/filter_state", FilterConfiguration::onOff()}}, move(filterPool)), m_desireSet(move(desireSet)), - m_nodeHandle(nodeHandle) + m_node(move(node)) { - m_gesturePublisher = nodeHandle.advertise("gesture/name", 1, true); - m_gestureDoneSubscriber = - nodeHandle.subscribe("gesture/done", 1, &GestureStrategy::gestureDoneSubscriberCallback, this); + m_gesturePublisher = + m_node->create_publisher("gesture/name", rclcpp::QoS(1).transient_local()); + m_gestureDoneSubscriber = m_node->create_subscription( + "gesture/done", + 1, + [this](const behavior_msgs::msg::Done::SharedPtr msg) { gestureDoneSubscriberCallback(msg); }); } StrategyType GestureStrategy::strategyType() @@ -190,13 +200,13 @@ StrategyType GestureStrategy::strategyType() void GestureStrategy::onEnabling(const GestureDesire& desire) { - gesture::GestureName msg; + behavior_msgs::msg::GestureName msg; msg.name = desire.name(); msg.id = desire.id(); - m_gesturePublisher.publish(msg); + m_gesturePublisher->publish(msg); } -void GestureStrategy::gestureDoneSubscriberCallback(const gesture::Done::ConstPtr& msg) +void GestureStrategy::gestureDoneSubscriberCallback(const behavior_msgs::msg::Done::SharedPtr msg) { if (msg->id == desireId()) { @@ -208,18 +218,21 @@ PlaySoundStrategy::PlaySoundStrategy( uint16_t utility, shared_ptr filterPool, shared_ptr desireSet, - ros::NodeHandle& nodeHandle) + shared_ptr node) : Strategy( utility, {{"sound", 1}}, {{"sound_player/filter_state", FilterConfiguration::onOff()}}, move(filterPool)), m_desireSet(desireSet), - m_nodeHandle(nodeHandle) + m_node(move(node)) { - m_pathPublisher = nodeHandle.advertise("sound_player/file", 1, true); - m_soundDoneSubscriber = - nodeHandle.subscribe("sound_player/done", 1, &PlaySoundStrategy::soundDoneSubscriberCallback, this); + m_pathPublisher = + m_node->create_publisher("sound_player/file", rclcpp::QoS(1).transient_local()); + m_soundDoneSubscriber = m_node->create_subscription( + "sound_player/done", + 1, + [this](const behavior_msgs::msg::Done::SharedPtr msg) { soundDoneSubscriberCallback(msg); }); } StrategyType PlaySoundStrategy::strategyType() @@ -229,13 +242,13 @@ StrategyType PlaySoundStrategy::strategyType() void PlaySoundStrategy::onEnabling(const PlaySoundDesire& desire) { - sound_player::SoundFile msg; + behavior_msgs::msg::SoundFile msg; msg.path = desire.path(); msg.id = desire.id(); - m_pathPublisher.publish(msg); + m_pathPublisher->publish(msg); } -void PlaySoundStrategy::soundDoneSubscriberCallback(const sound_player::Done::ConstPtr& msg) +void PlaySoundStrategy::soundDoneSubscriberCallback(const behavior_msgs::msg::Done::SharedPtr msg) { if (msg->id == desireId()) { @@ -395,24 +408,24 @@ unique_ptr createExploreStrategy(shared_ptr filterPool } unique_ptr - createFaceAnimationStrategy(shared_ptr filterPool, ros::NodeHandle& nodeHandle, uint16_t utility) + createFaceAnimationStrategy(shared_ptr filterPool, shared_ptr node, uint16_t utility) { - return make_unique(utility, move(filterPool), nodeHandle); + return make_unique(utility, move(filterPool), move(node)); } unique_ptr - createLedEmotionStrategy(shared_ptr filterPool, ros::NodeHandle& nodeHandle, uint16_t utility) + createLedEmotionStrategy(shared_ptr filterPool, shared_ptr node, uint16_t utility) { - return make_unique(utility, move(filterPool), nodeHandle); + return make_unique(utility, move(filterPool), move(node)); } unique_ptr createLedAnimationStrategy( shared_ptr filterPool, shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + shared_ptr node, uint16_t utility) { - return make_unique(utility, filterPool, desireSet, nodeHandle); + return make_unique(utility, filterPool, desireSet, move(node)); } unique_ptr createSoundFollowingStrategy(shared_ptr filterPool, uint16_t utility) @@ -437,10 +450,10 @@ unique_ptr createNearestFaceFollowingStrategy(shared_ptr createSpecificFaceFollowingStrategy( shared_ptr filterPool, - ros::NodeHandle& nodeHandle, + shared_ptr node, uint16_t utility) { - return make_unique(utility, move(filterPool), nodeHandle); + return make_unique(utility, move(filterPool), move(node)); } unique_ptr createSoundObjectPersonFollowingStrategy(shared_ptr filterPool, uint16_t utility) @@ -457,19 +470,19 @@ unique_ptr createSoundObjectPersonFollowingStrategy(shared_ptr createTalkStrategy( shared_ptr filterPool, shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + shared_ptr node, uint16_t utility) { - return make_unique(utility, move(filterPool), move(desireSet), nodeHandle); + return make_unique(utility, move(filterPool), move(desireSet), move(node)); } unique_ptr createGestureStrategy( shared_ptr filterPool, shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + shared_ptr node, uint16_t utility) { - return make_unique(utility, move(filterPool), move(desireSet), nodeHandle); + return make_unique(utility, move(filterPool), move(desireSet), move(node)); } unique_ptr createDanceStrategy(shared_ptr filterPool, uint16_t utility) @@ -489,10 +502,10 @@ unique_ptr createDanceStrategy(shared_ptr filterPool, unique_ptr createPlaySoundStrategy( shared_ptr filterPool, shared_ptr desireSet, - ros::NodeHandle& nodeHandle, + shared_ptr node, uint16_t utility) { - return make_unique(utility, move(filterPool), move(desireSet), nodeHandle); + return make_unique(utility, move(filterPool), move(desireSet), move(node)); } unique_ptr createTelepresenceStrategy(shared_ptr filterPool, uint16_t utility) diff --git a/ros/utils/t_top_hbba_lite/src/set_head_pose_arbitration_node.cpp b/ros/utils/t_top_hbba_lite/src/set_head_pose_arbitration_node.cpp index 568e4067..c37794a6 100644 --- a/ros/utils/t_top_hbba_lite/src/set_head_pose_arbitration_node.cpp +++ b/ros/utils/t_top_hbba_lite/src/set_head_pose_arbitration_node.cpp @@ -1,28 +1,30 @@ -#include -#include -#include -#include +#include -#include +#include +#include +#include + +#include #include #include using namespace std; +constexpr const char* NODE_NAME = "set_head_pose_arbitration_node"; constexpr const char* HEAD_POSE_FRAME_ID = "stewart_base"; struct Topic { string name; int priority; - ros::Duration timeout; + rclcpp::Duration timeout; }; -geometry_msgs::Pose defaultPose() +geometry_msgs::msg::Pose defaultPose() { - geometry_msgs::Pose pose; + geometry_msgs::msg::Pose pose; pose.position.x = 0.0; pose.position.y = 0.0; @@ -37,95 +39,137 @@ geometry_msgs::Pose defaultPose() } -class ArbitrationNode +class ArbitrationNode : public rclcpp::Node { - ros::NodeHandle& m_nodeHandle; - vector m_subscribers; - ros::Publisher m_publisher; - bool m_hasAdvertised; + vector::SharedPtr> m_subscribers; + rclcpp::Publisher::SharedPtr m_publisher; vector m_topics; optional m_currentTopicIndex; - ros::Time m_lastMessageTime; + rclcpp::Time m_lastMessageTime; - vector m_offsets; + vector m_offsets; - ros::Subscriber m_motorStatusSubscriber; - optional m_lastPose; + rclcpp::Subscription::SharedPtr m_motorStatusSubscriber; + optional m_lastPose; public: - ArbitrationNode(ros::NodeHandle& nodeHandle, vector topics, vector offsetTopics, bool latch) - : m_nodeHandle(nodeHandle), - m_hasAdvertised(false), - m_topics(move(topics)), - m_lastMessageTime(ros::Time::now()) + ArbitrationNode() : rclcpp::Node(NODE_NAME), m_lastMessageTime(get_clock()->now()) { + m_topics = convertToTopics( + declare_parameter("topics", vector{}), + declare_parameter("priorities", vector{}), + declare_parameter("timeout_s", vector{})); + if (!hasUniquePriority(m_topics)) + { + throw std::runtime_error("The topic priorities must be unique."); + } + for (size_t i = 0; i < m_topics.size(); i++) { - m_subscribers.emplace_back(m_nodeHandle.subscribe( + m_subscribers.emplace_back(create_subscription( m_topics[i].name, 1, - [this, i](const geometry_msgs::PoseStamped::ConstPtr& msg) { callback(i, msg); })); + [this, i](const geometry_msgs::msg::PoseStamped::SharedPtr msg) { callback(i, msg); })); } + auto offsetTopics = declare_parameter("offset_topics", vector{}); for (size_t i = 0; i < offsetTopics.size(); i++) { - m_subscribers.emplace_back(m_nodeHandle.subscribe( + m_subscribers.emplace_back(create_subscription( offsetTopics[i], 1, - [this, i](const geometry_msgs::PoseStamped::ConstPtr& msg) { offsetCallback(i, msg); })); + [this, i](const geometry_msgs::msg::PoseStamped::SharedPtr msg) { offsetCallback(i, msg); })); m_offsets.emplace_back(defaultPose()); } - m_publisher = m_nodeHandle.advertise("daemon/set_head_pose", 1, latch); + m_publisher = create_publisher("daemon/set_head_pose", 1); - m_motorStatusSubscriber = - m_nodeHandle.subscribe("daemon/motor_status", 1, &ArbitrationNode::motorStatusCallback, this); + m_motorStatusSubscriber = create_subscription( + "daemon/motor_status", + 1, + [this](const daemon_ros_client::msg::MotorStatus::SharedPtr msg) { motorStatusCallback(msg); }); } - void run() { ros::spin(); } + void run() { rclcpp::spin(shared_from_this()); } private: - void callback(size_t i, const geometry_msgs::PoseStamped::ConstPtr& msg) + vector + convertToTopics(const vector& topics, const vector& priorities, const vector& timeoutS) + { + if (topics.size() != priorities.size() || topics.size() != timeoutS.size()) + { + throw std::runtime_error("The topics, priorities, timeout_s parameters must have the same size."); + } + + vector convertedTopics; + for (size_t i = 0; i < topics.size(); i++) + { + auto expandedTopic = rclcpp::expand_topic_or_service_name(topics[i], get_name(), get_namespace(), false); + auto timeout = chrono::duration>(timeoutS[i]); + convertedTopics.emplace_back(Topic{expandedTopic, static_cast(priorities[i]), timeout}); + } + + return convertedTopics; + } + + bool hasUniquePriority(const vector& topics) + { + unordered_set priorities; + + for (auto& topic : topics) + { + if (priorities.count(topic.priority) > 0) + { + return false; + } + + priorities.insert(topic.priority); + } + + return true; + } + + void callback(size_t i, const geometry_msgs::msg::PoseStamped::SharedPtr msg) { if (msg->header.frame_id != HEAD_POSE_FRAME_ID) { - ROS_ERROR_STREAM("Invalid head pose frame id (" << msg->header.frame_id << ")"); + RCLCPP_ERROR_STREAM(get_logger(), "Invalid head pose frame id (" << msg->header.frame_id << ")"); return; } if (m_currentTopicIndex == nullopt || m_topics[i].priority <= m_topics[*m_currentTopicIndex].priority || - (ros::Time::now() - m_lastMessageTime) > m_topics[*m_currentTopicIndex].timeout) + (get_clock()->now() - m_lastMessageTime) > m_topics[*m_currentTopicIndex].timeout) { m_currentTopicIndex = i; - m_lastMessageTime = ros::Time::now(); - m_publisher.publish(applyOffsets(*msg)); + m_lastMessageTime = get_clock()->now(); + m_publisher->publish(applyOffsets(*msg)); m_lastPose = *msg; } } - void offsetCallback(size_t i, const geometry_msgs::PoseStamped::ConstPtr& msg) + void offsetCallback(size_t i, const geometry_msgs::msg::PoseStamped::SharedPtr msg) { if (msg->header.frame_id != HEAD_POSE_FRAME_ID) { - ROS_ERROR_STREAM("Invalid head pose frame id (" << msg->header.frame_id << ")"); + RCLCPP_ERROR_STREAM(get_logger(), "Invalid head pose frame id (" << msg->header.frame_id << ")"); return; } m_offsets[i] = msg->pose; if (m_lastPose.has_value()) { - m_publisher.publish(applyOffsets(*m_lastPose)); + m_publisher->publish(applyOffsets(*m_lastPose)); } } - geometry_msgs::PoseStamped applyOffsets(const geometry_msgs::PoseStamped& inputMsg) + geometry_msgs::msg::PoseStamped applyOffsets(const geometry_msgs::msg::PoseStamped& inputMsg) { double x = inputMsg.pose.position.x; double y = inputMsg.pose.position.y; double z = inputMsg.pose.position.z; - tf::Quaternion rotation( + tf2::Quaternion rotation( inputMsg.pose.orientation.x, inputMsg.pose.orientation.y, inputMsg.pose.orientation.z, @@ -138,10 +182,10 @@ class ArbitrationNode z += offset.position.z; rotation *= - tf::Quaternion(offset.orientation.x, offset.orientation.y, offset.orientation.z, offset.orientation.w); + tf2::Quaternion(offset.orientation.x, offset.orientation.y, offset.orientation.z, offset.orientation.w); } - geometry_msgs::PoseStamped outputMsg; + geometry_msgs::msg::PoseStamped outputMsg; outputMsg.header = inputMsg.header; outputMsg.pose.position.x = x; outputMsg.pose.position.y = y; @@ -153,11 +197,11 @@ class ArbitrationNode return outputMsg; } - void motorStatusCallback(const daemon_ros_client::MotorStatus::ConstPtr& msg) + void motorStatusCallback(const daemon_ros_client::msg::MotorStatus::SharedPtr msg) { if (m_lastPose == nullopt) { - m_lastPose = geometry_msgs::PoseStamped(); + m_lastPose = geometry_msgs::msg::PoseStamped(); m_lastPose->header.frame_id = msg->head_pose_frame_id; m_lastPose->pose = msg->head_pose; } @@ -165,91 +209,22 @@ class ArbitrationNode }; -bool getTopics(ros::NodeHandle& privateNodeHandle, vector& topics) -{ - vector value; - - XmlRpc::XmlRpcValue xmlTopics; - privateNodeHandle.getParam("topics", xmlTopics); - if (xmlTopics.getType() != XmlRpc::XmlRpcValue::TypeArray) - { - ROS_ERROR("Invalid topics format"); - return false; - } - - for (size_t i = 0; i < xmlTopics.size(); i++) - { - if (xmlTopics[i].getType() != XmlRpc::XmlRpcValue::TypeStruct || - xmlTopics[i]["name"].getType() != XmlRpc::XmlRpcValue::TypeString || - xmlTopics[i]["priority"].getType() != XmlRpc::XmlRpcValue::TypeInt || - xmlTopics[i]["timeout_s"].getType() != XmlRpc::XmlRpcValue::TypeDouble) - { - ROS_ERROR_STREAM("Invalid topics[" << i << "]: name must be a string and priority must be a int and."); - return false; - } - - topics.emplace_back(Topic{ - static_cast(xmlTopics[i]["name"]), - static_cast(xmlTopics[i]["priority"]), - ros::Duration(static_cast(xmlTopics[i]["timeout_s"]))}); - } - - return topics.size() > 0; -} - -bool hasUniquePriorities(const vector& topics) -{ - unordered_set priorities; - - for (auto& topic : topics) - { - if (priorities.count(topic.priority) > 0) - { - return false; - } - - priorities.insert(topic.priority); - } - - return true; -} - - int main(int argc, char** argv) { - ros::init(argc, argv, "arbitration_node"); - - ros::NodeHandle nodeHandle; - ros::NodeHandle privateNodeHandle("~"); + rclcpp::init(argc, argv); - vector topics; - if (!getTopics(privateNodeHandle, topics)) + try { - ROS_ERROR("The parameter topics must be set, not empty and valid."); - return -1; + auto node = std::make_shared(); + node->run(); + rclcpp::shutdown(); } - if (!hasUniquePriorities(topics)) + catch (const std::exception& e) { - ROS_ERROR("The topic priorities must be unique."); + RCLCPP_ERROR(rclcpp::get_logger(NODE_NAME), "%s", e.what()); + rclcpp::shutdown(); return -1; } - vector offsetTopics; - if (!privateNodeHandle.getParam("offset_topics", offsetTopics)) - { - ROS_ERROR("The parameter offset_topics must be set."); - return false; - } - - bool latch; - if (!privateNodeHandle.getParam("latch", latch)) - { - ROS_ERROR("The parameter latch is required."); - return -1; - } - - ArbitrationNode node(nodeHandle, topics, offsetTopics, latch); - node.run(); - return 0; } diff --git a/ros/utils/time_utils/CMakeLists.txt b/ros/utils/time_utils/CMakeLists.txt new file mode 100644 index 00000000..83b76886 --- /dev/null +++ b/ros/utils/time_utils/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.5) +project(time_utils) + +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclpy REQUIRED) + + +# Python Librairies +ament_python_install_package(${PROJECT_NAME}) + + +ament_package() diff --git a/ros/utils/time_utils/README.md b/ros/utils/time_utils/README.md new file mode 100644 index 00000000..5762cfa3 --- /dev/null +++ b/ros/utils/time_utils/README.md @@ -0,0 +1,5 @@ +# time_utils + +Available classes : + +* Rate(hz) : Same behavior as ROS1. Sleep the process at the determined rate/frequency by calling Rate.sleep(). diff --git a/ros/utils/time_utils/package.xml b/ros/utils/time_utils/package.xml new file mode 100644 index 00000000..f2549e7f --- /dev/null +++ b/ros/utils/time_utils/package.xml @@ -0,0 +1,23 @@ + + + + time_utils + 0.0.0 + The time_utils package + Marc-Antoine Maheux + GPL-3.0 license + + ament_cmake + + rclpy + + rosidl_default_runtime + rosidl_interface_packages + + ament_lint_auto + ament_lint_common + + + ament_cmake + + diff --git a/ros/utils/time_utils/time_utils/__init__.py b/ros/utils/time_utils/time_utils/__init__.py new file mode 100644 index 00000000..10365873 --- /dev/null +++ b/ros/utils/time_utils/time_utils/__init__.py @@ -0,0 +1,23 @@ +import time + +class Rate: + + def __init__(self, hz): + self._last_time_s = time.time() + self._sleep_duration_s = 1 / hz if hz > 0.0 else 0.0 + + def sleep(self): + curr_time_s = time.time() + # detect time jumping backwards + if self._last_time_s > curr_time_s: + self._last_time_s = curr_time_s + + # calculate sleep interval + elapsed_s = curr_time_s - self._last_time_s + time.sleep(self._sleep_duration_s - elapsed_s) + self._last_time_s = self._last_time_s + self._sleep_duration_s + + # detect time jumping forwards, as well as loops that are + # inherently too slow + if curr_time_s - self._last_time_s > self._sleep_duration_s * 2: + self._last_time_s = curr_time_s diff --git a/ros/utils/watchdog/CMakeLists.txt b/ros/utils/watchdog/CMakeLists.txt index b9a677d8..3ff7b7da 100644 --- a/ros/utils/watchdog/CMakeLists.txt +++ b/ros/utils/watchdog/CMakeLists.txt @@ -1,207 +1,38 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.5) project(watchdog) -## Compile as C++11, supported in ROS Kinetic and newer -# add_compile_options(-std=c++11) -## Find catkin macros and libraries -## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) -## is used, also find other catkin packages -find_package(catkin REQUIRED COMPONENTS - roscpp - rospy - std_msgs - topic_tools -) - -## System dependencies are found with CMake's conventions -# find_package(Boost REQUIRED COMPONENTS system) - - -## Uncomment this if the package has a setup.py. This macro ensures -## modules and global scripts declared therein get installed -## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html -# catkin_python_setup() - -################################################ -## Declare ROS messages, services and actions ## -################################################ - -## To declare and build messages, services or actions from within this -## package, follow these steps: -## * Let MSG_DEP_SET be the set of packages whose message types you use in -## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...). -## * In the file package.xml: -## * add a build_depend tag for "message_generation" -## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET -## * If MSG_DEP_SET isn't empty the following dependency has been pulled in -## but can be declared for certainty nonetheless: -## * add a exec_depend tag for "message_runtime" -## * In this file (CMakeLists.txt): -## * add "message_generation" and every package in MSG_DEP_SET to -## find_package(catkin REQUIRED COMPONENTS ...) -## * add "message_runtime" and every package in MSG_DEP_SET to -## catkin_package(CATKIN_DEPENDS ...) -## * uncomment the add_*_files sections below as needed -## and list every .msg/.srv/.action file to be processed -## * uncomment the generate_messages entry below -## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...) - -## Generate messages in the 'msg' folder -# add_message_files( -# FILES -# Message1.msg -# Message2.msg -# ) - -## Generate services in the 'srv' folder -# add_service_files( -# FILES -# Service1.srv -# Service2.srv -# ) - -## Generate actions in the 'action' folder -# add_action_files( -# FILES -# Action1.action -# Action2.action -# ) - -## Generate added messages and services with any dependencies listed here -# generate_messages( -# DEPENDENCIES -# std_msgs -# ) - -################################################ -## Declare ROS dynamic reconfigure parameters ## -################################################ - -## To declare and build dynamic reconfigure parameters within this -## package, follow these steps: -## * In the file package.xml: -## * add a build_depend and a exec_depend tag for "dynamic_reconfigure" -## * In this file (CMakeLists.txt): -## * add "dynamic_reconfigure" to -## find_package(catkin REQUIRED COMPONENTS ...) -## * uncomment the "generate_dynamic_reconfigure_options" section below -## and list every .cfg file to be processed - -## Generate dynamic reconfigure parameters in the 'cfg' folder -# generate_dynamic_reconfigure_options( -# cfg/DynReconf1.cfg -# cfg/DynReconf2.cfg -# ) - -################################### -## catkin specific configuration ## -################################### -## The catkin_package macro generates cmake config files for your package -## Declare things to be passed to dependent projects -## INCLUDE_DIRS: uncomment this if your package contains header files -## LIBRARIES: libraries you create in this project that dependent projects also need -## CATKIN_DEPENDS: catkin_packages dependent projects also need -## DEPENDS: system dependencies of this project that dependent projects also need -catkin_package( -# INCLUDE_DIRS include -# LIBRARIES watchdog -# CATKIN_DEPENDS roscpp rospy std_msgs topic_tools -# DEPENDS system_lib -) - -########### -## Build ## -########### +# Default to C99 +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() -## Specify additional locations of header files -## Your package locations should be listed before other locations -include_directories( -# include - ${catkin_INCLUDE_DIRS} -) +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +endif() -## Declare a C++ library -# add_library(${PROJECT_NAME} -# src/${PROJECT_NAME}/watchdog.cpp -# ) +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() -## Add cmake target dependencies of the library -## as an example, code may need to be generated before libraries -## either from message generation or dynamic reconfigure -# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) +# Find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclcpp REQUIRED) +find_package(rclpy REQUIRED) -## Declare a C++ executable -## With catkin_make all packages are built within a single CMake context -## The recommended prefix ensures that target names across packages don't collide +# C++ Nodes add_executable(watchdog_node src/watchdog_node.cpp) +ament_target_dependencies(watchdog_node rclcpp) +install(TARGETS watchdog_node DESTINATION lib/${PROJECT_NAME}) -## Rename C++ executable without prefix -## The above recommended prefix causes long target names, the following renames the -## target back to the shorter version for ease of user use -## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node" -# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "") - -## Add cmake target dependencies of the executable -## same as for the library above -# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - -## Specify libraries to link a library or executable target against -target_link_libraries(watchdog_node - ${catkin_LIBRARIES} -) - -############# -## Install ## -############# - -# all install targets should use catkin DESTINATION variables -# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html - -## Mark executable scripts (Python etc.) for installation -## in contrast to setup.py, you can choose the destination -catkin_install_python(PROGRAMS +# Python Nodes +install(PROGRAMS scripts/test_node.py - DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} + DESTINATION lib/${PROJECT_NAME} ) -## Mark executables for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html -# install(TARGETS ${PROJECT_NAME}_node -# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -# ) - -## Mark libraries for installation -## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html -# install(TARGETS ${PROJECT_NAME} -# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} -# RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} -# ) - -## Mark cpp header files for installation -# install(DIRECTORY include/${PROJECT_NAME}/ -# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} -# FILES_MATCHING PATTERN "*.h" -# PATTERN ".svn" EXCLUDE -# ) - -## Mark other files for installation (e.g. launch and bag files, etc.) -# install(FILES -# # myfile1 -# # myfile2 -# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} -# ) - -############# -## Testing ## -############# - -## Add gtest based cpp test target and link libraries -# catkin_add_gtest(${PROJECT_NAME}-test test/test_watchdog.cpp) -# if(TARGET ${PROJECT_NAME}-test) -# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) -# endif() +# Launch files +install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}) -## Add folders to be run by python nosetests -# catkin_add_nosetests(test) +ament_package() diff --git a/ros/utils/watchdog/launch/test_watchdog.launch b/ros/utils/watchdog/launch/test_watchdog.launch.xml similarity index 67% rename from ros/utils/watchdog/launch/test_watchdog.launch rename to ros/utils/watchdog/launch/test_watchdog.launch.xml index 1ff962f0..d0e413ae 100644 --- a/ros/utils/watchdog/launch/test_watchdog.launch +++ b/ros/utils/watchdog/launch/test_watchdog.launch.xml @@ -1,11 +1,12 @@ - + - + + diff --git a/ros/utils/watchdog/package.xml b/ros/utils/watchdog/package.xml index de919d9d..b8971548 100644 --- a/ros/utils/watchdog/package.xml +++ b/ros/utils/watchdog/package.xml @@ -1,71 +1,26 @@ - + + watchdog 0.0.0 The watchdog package + Marc-Antoine Maheux + GPL-3.0 license - - - - marc-antoine + ament_cmake + rclcpp + rclpy - - - - TODO + rosidl_default_runtime + ros2launch + rosidl_interface_packages + ament_lint_auto + ament_lint_common + ament_cmake_gtest - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - catkin - roscpp - rospy - std_msgs - topic_tools - roscpp - rospy - std_msgs - topic_tools - roscpp - rospy - std_msgs - topic_tools - - - - - + ament_cmake diff --git a/ros/utils/watchdog/scripts/test_node.py b/ros/utils/watchdog/scripts/test_node.py index 1dab3453..a61bdf67 100755 --- a/ros/utils/watchdog/scripts/test_node.py +++ b/ros/utils/watchdog/scripts/test_node.py @@ -1,38 +1,47 @@ #!/usr/bin/env python3 -import rospy +import rclpy +import rclpy.node from std_msgs.msg import Empty -class TestNode: +class TestNode(rclpy.node.Node): def __init__(self): - self._startup_delay_s = rospy.get_param('~startup_delay_s', 1.5) - self._freeze_delay_s = rospy.get_param('~freeze_delay_s', 10.0) - self._message_frequency = rospy.get_param('~message_frequency', 10.0) + super().__init__('test_node') - self._pub = rospy.Publisher('topic', Empty, queue_size=1) - self._rate = rospy.Rate(self._message_frequency) + self._startup_delay_ns = self.declare_parameter('startup_delay_s', 1.5).get_parameter_value().double_value * 1e9 + self._freeze_delay_ns = self.declare_parameter('freeze_delay_s', 10.0).get_parameter_value().double_value * 1e9 + self._message_frequency = self.declare_parameter('message_frequency', 10.0).get_parameter_value().double_value - def run(self): - startup_time_s = rospy.get_time() + self._pub = self.create_publisher(Empty, 'topic', 1) + + self._timer = self.create_timer(1 / self._message_frequency, self._timer_callback) - while not rospy.is_shutdown(): - startup_duration = rospy.get_time() - startup_time_s - if startup_duration > self._startup_delay_s and startup_duration < self._freeze_delay_s: - self._pub.publish(Empty()) + self._startup_time = self.get_clock().now() - self._rate.sleep() + def _timer_callback(self): + startup_duration = self.get_clock().now() - self._startup_time + if startup_duration.nanoseconds > self._startup_delay_ns and startup_duration.nanoseconds < self._freeze_delay_ns: + self._pub.publish(Empty()) + + def run(self): + rclpy.spin(self) def main(): - rospy.init_node('test_node') + rclpy.init() test_node = TestNode() - test_node.run() - -if __name__ == '__main__': try: - main() - except rospy.ROSInterruptException: + test_node.run() + except KeyboardInterrupt: pass + finally: + test_node.destroy_node() + if rclpy.ok(): + rclpy.shutdown() + + +if __name__ == '__main__': + main() diff --git a/ros/utils/watchdog/src/watchdog_node.cpp b/ros/utils/watchdog/src/watchdog_node.cpp index cc149187..101f705b 100644 --- a/ros/utils/watchdog/src/watchdog_node.cpp +++ b/ros/utils/watchdog/src/watchdog_node.cpp @@ -1,131 +1,126 @@ -#include -#include -#include -#include - -#include +#include #include #include +#include +#include +#include + using namespace std; +namespace fs = std::filesystem; -constexpr bool ONE_SHOT = true; +string readFile(const fs::path& path) +{ + std::ifstream t(path); + std::stringstream ss; + ss << t.rdbuf(); + return ss.str(); +} bool getNodePid(const string& nodeName, int& pid) { - XmlRpc::XmlRpcValue req; - req[0] = ros::this_node::getName(); - req[1] = nodeName; - - XmlRpc::XmlRpcValue resp; - XmlRpc::XmlRpcValue payload; - if (!ros::master::execute("lookupNode", req, resp, payload, true)) - { - ROS_ERROR_STREAM("Failed to lookup the watched node (" << nodeName << ")."); - return false; - } - - string peerHost; - uint32_t peerPort; - if (!ros::network::splitURI(static_cast(resp[2]), peerHost, peerPort)) - { - ROS_ERROR_STREAM("Invalid API URI (" << resp[2] << ")"); - return false; - } + auto arg = "__node:=" + nodeName; - XmlRpc::XmlRpcClient c(peerHost.c_str(), peerPort, "/"); - XmlRpc::XmlRpcValue req2; - XmlRpc::XmlRpcValue resp2; - req2[0] = ros::this_node::getName(); - c.execute("getPid", req2, resp2); - if (c.isFault() || !resp2.valid() || static_cast(resp2[0]) != 1) + for (const auto& entry : fs::directory_iterator("/proc")) { - ROS_ERROR_STREAM("Failed to fetch the pid of " << nodeName << "."); - return false; + if (readFile(entry.path() / "cmdline").find(arg) != string::npos) + { + pid = stoi(entry.path().filename()); + return true; + } } - pid = static_cast(resp2[2]); - return true; -} - -void killNode(const string& nodeName) -{ - int pid; - if (getNodePid(nodeName, pid)) - { - ROS_ERROR_STREAM("Killing PID: " << pid); - kill(pid, SIGINT); - } + return false; } -class WatchdogNode +class WatchdogNode : public rclcpp::Node { - ros::NodeHandle& m_nodeHandle; - string m_nodeName; - ros::Duration m_timeoutDuration; + string m_topic; + chrono::milliseconds m_timeoutDuration; - ros::Time m_lastStartupTime; + rclcpp::TimerBase::SharedPtr m_initTimer; - ros::Subscriber m_subscriber; - ros::Timer m_messageTimer; + rclcpp::GenericSubscription::SharedPtr m_subscriber; + rclcpp::TimerBase::SharedPtr m_messageTimer; public: - WatchdogNode(ros::NodeHandle& nodeHandle, string nodeName, ros::Duration timeoutDuration) - : m_nodeHandle(nodeHandle), - m_nodeName(move(nodeName)), - m_timeoutDuration(timeoutDuration) + WatchdogNode() : rclcpp::Node("watchdog_node") { - m_lastStartupTime = ros::Time::now(); + m_nodeName = declare_parameter("node_name", ""); + m_topic = rclcpp::expand_topic_or_service_name(declare_parameter("topic", ""), get_name(), get_namespace(), false); + RCLCPP_INFO_STREAM(get_logger(), "Listening on: " << m_topic); - m_subscriber = nodeHandle.subscribe("topic", 1, &WatchdogNode::topicCallback, this); + double timeoutDurationS = declare_parameter("timeout_duration_s", 60.0); + m_timeoutDuration = chrono::milliseconds(static_cast(timeoutDurationS * 1000)); + + m_initTimer = create_wall_timer(std::chrono::seconds(1), [this]() { initTimerCallback(); }); } - void run() { ros::spin(); } + void run() { rclcpp::spin(shared_from_this()); } private: - void topicCallback(const ros::MessageEvent& msgEvent) + void initTimerCallback() { - if (m_messageTimer.isValid()) + auto all_topics_and_types = get_topic_names_and_types(); + auto it = all_topics_and_types.find(m_topic); + if (it == all_topics_and_types.end() || it->second.empty()) { - m_messageTimer.stop(); + return; } - m_messageTimer = - m_nodeHandle.createTimer(m_timeoutDuration, &WatchdogNode::messageTimerCallback, this, ONE_SHOT); + RCLCPP_INFO_STREAM(get_logger(), "Topic type found: " << it->second[0]); + + m_subscriber = create_generic_subscription(m_topic, it->second[0], 1, + [this](std::shared_ptr msg) + { + topicCallback(); + }); + + m_initTimer->cancel(); + } + + void topicCallback() + { + if (m_messageTimer) + { + m_messageTimer->reset(); + } + else + { + m_messageTimer = create_wall_timer(m_timeoutDuration, [this]() { messageTimerCallback(); }); + } } - void messageTimerCallback(const ros::TimerEvent&) + void messageTimerCallback() { - ROS_ERROR_STREAM("The node '" << m_nodeName << "' is no longer responding. The node will be respawned."); + RCLCPP_ERROR_STREAM(get_logger(), "The node '" << m_nodeName << "' is no longer responding. The node will be respawned."); killNode(m_nodeName); + + m_messageTimer->cancel(); + m_messageTimer = nullptr; + } + + void killNode(const string& nodeName) + { + int pid; + if (getNodePid(nodeName, pid)) + { + RCLCPP_ERROR_STREAM(get_logger(), "Killing PID: " << pid); + kill(pid, SIGINT); + } } }; int main(int argc, char** argv) { - ros::init(argc, argv, "beat_detector_node"); - - ros::NodeHandle nodeHandle; - ros::NodeHandle privateNodeHandle("~"); + rclcpp::init(argc, argv); - string nodeName; - double timeoutDurationS; - - if (!privateNodeHandle.getParam("node_name", nodeName)) - { - ROS_ERROR("The parameter node_name is required."); - return -1; - } - if (!privateNodeHandle.getParam("timeout_duration_s", timeoutDurationS)) - { - ROS_ERROR("The parameter timeout_duration_s is required."); - return -1; - } + auto node = std::make_shared(); + node->run(); - WatchdogNode node(nodeHandle, nodeName, ros::Duration(timeoutDurationS)); - node.run(); + rclcpp::shutdown(); return 0; } diff --git a/system/daemon/COLCON_IGNORE b/system/daemon/COLCON_IGNORE new file mode 100644 index 00000000..e69de29b diff --git a/system/daemon/src/DaemonApp.cpp b/system/daemon/src/DaemonApp.cpp index 9780c021..9b926d6b 100644 --- a/system/daemon/src/DaemonApp.cpp +++ b/system/daemon/src/DaemonApp.cpp @@ -210,7 +210,7 @@ void DaemonApp::setScreenBrightness(float front, float back, float left, float r void DaemonApp::terminateAllROSProcessesAndShutdown() { #ifdef __linux__ - auto pids = listPidsMatchingTheCriteria("roslaunch"); + auto pids = listPidsMatchingTheCriteria("ros2 launch"); qDebug() << "Shutdown of roslaunch processes (" << pids << ")"; shutdownProcessesAndWait(pids, SHUTDOWN_TIMEOUT_SEC); qDebug() << "Shutdown of roslaunch processes completed"; diff --git a/system/system_tray/COLCON_IGNORE b/system/system_tray/COLCON_IGNORE new file mode 100644 index 00000000..e69de29b diff --git a/tools/setup_scripts/files/colcon_defaults.yaml b/tools/setup_scripts/files/colcon_defaults.yaml new file mode 100644 index 00000000..e3250383 --- /dev/null +++ b/tools/setup_scripts/files/colcon_defaults.yaml @@ -0,0 +1,9 @@ +build: + cmake-args: + - -DCMAKE_EXPORT_COMPILE_COMMANDS=ON + - --no-warn-unused-cli + - -DPYTHON_EXECUTABLE=/usr/bin/python3 + - -DCMAKE_BUILD_TYPE=Release + - -DCMAKE_CXX_FLAGS=-march=native -ffast-math + - -DCMAKE_C_FLAGS=-march=native -ffast-math + symlink-install: true diff --git a/tools/setup_scripts/files/requirements.txt b/tools/setup_scripts/files/requirements.txt index e9130713..a44dd086 100644 --- a/tools/setup_scripts/files/requirements.txt +++ b/tools/setup_scripts/files/requirements.txt @@ -17,3 +17,4 @@ git+https://github.com/cocodataset/cocoapi.git#subdirectory=PythonAPI protobuf==3.20.3 grpcio-status==1.48.2 faster-whisper==0.9.0 +transforms3d diff --git a/tools/setup_scripts/jetson_configuration.sh b/tools/setup_scripts/jetson_configuration.sh index c6d9c25e..81b8f1fc 100755 --- a/tools/setup_scripts/jetson_configuration.sh +++ b/tools/setup_scripts/jetson_configuration.sh @@ -1,5 +1,16 @@ #! /usr/bin/bash +export ROS_DISTRO=humble +export ROS_PACKAGE=desktop_full +export ROS_ROOT=/opt/ros/$ROS_DISTRO +export ROS_PYTHON_VERSION=3 +export DEBIAN_FRONTEND=noninteractive +export PYTHONIOENCODING=utf-8 + +# Required for jetpack to find cuda +export PATH=/usr/local/cuda-11.4/bin:$PATH +export LD_LIBRARY_PATH=/usr/local/cuda-11.4/lib64:$LD_LIBRARY_PATH + set -e BLUE='\033[0;34m' @@ -87,6 +98,14 @@ clone_git () { fi } +sudo_clone_git () { + # arg 1: git clone command + local FOLDER=$(echo $@ | perl -pe 's|.*/(.*)\.git.*|$1|') + if [ ! -d "$FOLDER/.git" ] ; then + sudo git clone $@ + fi +} + apply_patch () { patch --dry-run -uN $@ | grep --quiet --no-messages "previously applied.*Skipping patch" || patch -u $@ } @@ -146,13 +165,62 @@ sudo apt upgrade -y sudo apt autoremove -y ECHO_IN_BLUE "###############################################################\n" +ECHO_IN_BLUE "###############################################################" +ECHO_IN_BLUE ">> Installing tools" +ECHO_IN_BLUE "###############################################################" +if [ $(checkstamp install_tools) = "false" ] ; then + sudo apt install -y htop python3-pip perl rsync scons + sudo apt-get install -y --no-install-recommends \ + git \ + curl \ + wget \ + gnupg2 \ + lsb-release \ + ca-certificates \ + git \ + libgtk-3-dev \ + libglfw3-dev \ + libgl1-mesa-dev \ + libglu1-mesa-dev \ + build-essential \ + cmake \ + cmake-curses-gui \ + libssl-dev \ + libusb-1.0-0-dev \ + libudev-dev \ + pkg-config + sudo -H pip3 install -U jetson-stats + makestamp install_tools +else + SKIP_SECTION "Tools already installed, skipping" +fi +ECHO_IN_BLUE "###############################################################\n" + +ECHO_IN_BLUE "###############################################################" +ECHO_IN_BLUE ">> Setting System Locale to en_US.UTF-8" +ECHO_IN_BLUE "###############################################################" +sudo update-locale LANG=en_US.UTF-8 +ECHO_IN_BLUE "###############################################################\n" + +ECHO_IN_BLUE "###############################################################" +ECHO_IN_BLUE ">> Setting Python3 as default" +ECHO_IN_BLUE "###############################################################" +if [ $(checkstamp python3_default) = "false" ] ; then + sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 1 + makestamp python3_default +else + SKIP_SECTION "Python3 is already the default, skipping" +fi +ECHO_IN_BLUE "###############################################################\n" + + ECHO_IN_BLUE "###############################################################" ECHO_IN_BLUE ">> Cloning the T-Top repo" ECHO_IN_BLUE "###############################################################" if [ $(checkstamp ttop_repo) = "false" ] ; then mkdir -p ~/t-top_ws/src cd ~/t-top_ws/src - clone_git --recurse-submodules https://github.com/introlab/t-top.git + clone_git --recurse-submodules https://github.com/introlab/t-top.git -b ros2 makestamp ttop_repo else SKIP_SECTION "T-Top repo already cloned, skipping" @@ -237,7 +305,7 @@ ECHO_IN_BLUE ">> Installing NPM and Node" ECHO_IN_BLUE "###############################################################" if [ $(checkstamp node) = "false" ] ; then sudo apt install -y curl software-properties-common - curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash - + curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash - sudo apt install -y nodejs makestamp node else @@ -246,121 +314,53 @@ fi ECHO_IN_BLUE "###############################################################\n" ECHO_IN_BLUE "###############################################################" -ECHO_IN_BLUE ">> Installing tools" -ECHO_IN_BLUE "###############################################################" -if [ $(checkstamp install_tools) = "false" ] ; then - sudo apt install -y htop python3-pip perl rsync scons - sudo -H pip3 install -U jetson-stats - makestamp install_tools -else - SKIP_SECTION "Tools already installed, skipping" -fi -ECHO_IN_BLUE "###############################################################\n" - -ECHO_IN_BLUE "###############################################################" -ECHO_IN_BLUE ">> Updating CMake" -ECHO_IN_BLUE "###############################################################" -if [ $(checkstamp cmake) = "false" ] ; then - wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | sudo tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null - sudo apt-add-repository "deb https://apt.kitware.com/ubuntu/ $(lsb_release -cs) main" - sudo apt update - sudo apt install -y cmake - makestamp cmake -else - SKIP_SECTION "CMake already installed, skipping" -fi -ECHO_IN_BLUE "###############################################################\n" - -ECHO_IN_BLUE "###############################################################" -ECHO_IN_BLUE ">> Cloning Librealsense 2" -ECHO_IN_BLUE "###############################################################" -if [ $(checkstamp librealsense_clone) = "false" ] ; then - mkdir -p ~/deps - cd ~/deps - clone_git https://github.com/jetsonhacks/buildLibrealsense2Xavier.git - makestamp librealsense_clone -else - SKIP_SECTION "Librealsense 2 already cloned, skipping" -fi -ECHO_IN_BLUE "###############################################################\n" - -ECHO_IN_BLUE "###############################################################" -ECHO_IN_BLUE ">> Patching Librealsense 2" -ECHO_IN_BLUE "###############################################################" -cd ~/deps/buildLibrealsense2Xavier -apply_patch installLibrealsense.sh $PATCH_FILES_DIR/installLibrealsense.patch -ECHO_IN_BLUE "###############################################################\n" - -ECHO_IN_BLUE "###############################################################" -ECHO_IN_BLUE ">> Building and installing Librealsense 2" -ECHO_IN_BLUE "###############################################################" -if [ $(checkstamp librealsense_build) = "false" ] ; then - cd ~/deps/buildLibrealsense2Xavier - # Installed later on, but will cause a failure if installed now - sudo apt autoremove -y libapriltag-dev - yes | ./installLibrealsense.sh - makestamp librealsense_build -else - SKIP_SECTION "Librealsense 2 already built, skipping" -fi -ECHO_IN_BLUE "###############################################################\n" - -ECHO_IN_BLUE "###############################################################" -ECHO_IN_BLUE ">> Install ROS build dependencies" +ECHO_IN_BLUE ">> Install ROS2 build dependencies" ECHO_IN_BLUE "###############################################################" if [ $(checkstamp ros_build_deps) = "false" ] ; then - sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list' - curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add - - sudo apt update + sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg + sudo echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/ros2.list > /dev/null + sudo apt-get update + + sudo apt-get install -y --no-install-recommends \ + build-essential \ + libbullet-dev \ + libpython3-dev \ + python3-colcon-common-extensions \ + python3-flake8 \ + python3-pip \ + python3-numpy \ + python3-pytest-cov \ + python3-rosdep \ + python3-setuptools \ + python3-vcstool \ + python3-rosinstall-generator \ + libasio-dev \ + libtinyxml2-dev \ + libcunit1-dev + + sudo pip3 install --upgrade --no-cache-dir \ + argcomplete \ + flake8-blind-except \ + flake8-builtins \ + flake8-class-newline \ + flake8-comprehensions \ + flake8-deprecated \ + flake8-docstrings \ + flake8-import-order \ + flake8-quotes \ + pytest-repeat \ + pytest-rerunfailures \ + pytest + + sudo python3 -m pip install --upgrade pip + sudo pip3 install --no-cache-dir scikit-build + sudo pip3 install --upgrade --no-cache-dir --verbose cmake==3.24.3 + + # remove other versions of Python3 + # workaround for 'Could NOT find Python3 (missing: Python3_NumPy_INCLUDE_DIRS Development' + sudo apt purge -y python3.9 libpython3.9* || echo "python3.9 not found, skipping removal" - sudo apt install -y \ - python3-rosdep \ - python3-rosinstall-generator \ - python3-vcstool \ - python3-catkin-tools \ - build-essential \ - libboost-all-dev \ - libpoco-dev python3-empy \ - libtinyxml-dev \ - libtinyxml2-dev \ - qt5-default \ - sip-dev \ - python3-sip \ - python3-sip-dbg \ - python3-sip-dev \ - python3-pyqt5 \ - python3-nose \ - python3-twisted \ - python3-serial \ - python3-autobahn \ - python3-tornado \ - python3-bson \ - python3-qt-binding \ - libcurl4-gnutls-dev \ - libgtest-dev \ - liblz4-dev \ - libfltk1.3-dev \ - liburdfdom-headers-dev \ - liburdfdom-dev \ - liburdfdom-tools \ - libgpgme-dev \ - libyaml-cpp-dev \ - libpcl-dev \ - libgtk-3-dev \ - libassimp-dev \ - libogre-1.9-dev \ - libconfig-dev \ - liblog4cplus-dev \ - alsa-utils \ - liblog4cpp5-dev \ - liblog4cxx-dev \ - libbz2-dev \ - libbullet-dev \ - libsdl1.2-dev \ - libsdl-image1.2-dev \ - libapriltag-dev \ - libdc1394-22-dev makestamp ros_build_deps else SKIP_SECTION "ROS build dependencies already installed, skipping" @@ -368,38 +368,7 @@ fi ECHO_IN_BLUE "###############################################################\n" ECHO_IN_BLUE "###############################################################" -ECHO_IN_BLUE ">> Install ROS system dependencies" -ECHO_IN_BLUE "###############################################################" -if [ $(checkstamp ros_system_deps) = "false" ] ; then - - cd ~/deps - clone_git https://github.com/ros/console_bridge.git - cd console_bridge - cmake_build_install_native - - cd ~/deps - clone_git https://github.com/ethz-asl/libnabo.git -b 1.0.7 - cd libnabo - cmake_build_install_native - - cd ~/deps - clone_git https://github.com/ethz-asl/libpointmatcher.git -b 1.3.1 - cd libpointmatcher - cmake_build_install_native - - cd ~/deps - clone_git -b 0.21.1-noetic https://github.com/introlab/rtabmap.git - cd rtabmap - cmake_build_install_native 4 - - makestamp ros_system_deps -else - SKIP_SECTION "ROS system dependencies already installed, skipping" -fi -ECHO_IN_BLUE "###############################################################\n" - -ECHO_IN_BLUE "###############################################################" -ECHO_IN_BLUE ">> Generate ROS build workspace and install dependencies" +ECHO_IN_BLUE ">> Generate ROS2 build workspace and install dependencies" ECHO_IN_BLUE "###############################################################" if [ $(checkstamp ros_ws_deps) = "false" ] ; then @@ -408,12 +377,58 @@ if [ $(checkstamp ros_ws_deps) = "false" ] ; then fi rosdep update - mkdir -p ~/ros_catkin_ws/src - cd ~/ros_catkin_ws - - rosinstall_generator desktop_full --rosdistro noetic --deps --tar > noetic-desktop.rosinstall - vcs import --input noetic-desktop.rosinstall ./src - rosdep install --from-paths ./src --ignore-packages-from-source --rosdistro noetic -y + # create the ROS_ROOT directory + mkdir -p ${ROS_ROOT}/src + cd ${ROS_ROOT} + + sudo bash -c "rosinstall_generator --deps --rosdistro ${ROS_DISTRO} ${ROS_PACKAGE} \ + launch_xml \ + launch_yaml \ + launch_testing \ + launch_testing_ament_cmake \ + demo_nodes_cpp \ + demo_nodes_py \ + example_interfaces \ + camera_calibration_parsers \ + camera_info_manager \ + cv_bridge \ + v4l2_camera \ + vision_opencv \ + vision_msgs \ + image_geometry \ + image_pipeline \ + image_transport \ + compressed_image_transport \ + compressed_depth_image_transport \ + rosbag2_storage_mcap \ + rtabmap \ + rtabmap_ros \ + diagnostics \ + imu_tools \ + rosbridge_suite \ + tf_transformations \ + joint_state_publisher_gui \ + rqt_tf_tree \ + > ros2.${ROS_DISTRO}.${ROS_PACKAGE}.rosinstall" + + sudo vcs import --retry 100 src < ros2.${ROS_DISTRO}.${ROS_PACKAGE}.rosinstall + + SKIP_KEYS="libopencv-dev libopencv-contrib-dev libopencv-imgproc-dev python-opencv python3-opencv xsimd xtensor xtl" + sudo rosdep update + sudo rosdep install -y \ + --ignore-src \ + --from-paths src \ + --rosdistro ${ROS_DISTRO} \ + --skip-keys "$SKIP_KEYS" + + cd ${ROS_ROOT}/src + sudo_clone_git -b master https://github.com/Kapernikov/cv_camera.git --depth 1 --recurse-submodules + sudo_clone_git -b 0.7.0 https://github.com/xtensor-stack/xtl.git --depth 1 --recurse-submodules + sudo_clone_git -b 7.4.8 https://github.com/xtensor-stack/xsimd.git --depth 1 --recurse-submodules + sudo_clone_git -b 0.23.10 https://github.com/xtensor-stack/xtensor.git --depth 1 --recurse-submodules + + sudo_apply_patch ${ROS_ROOT}/src/libg2o/CMakeLists.txt $PATCH_FILES_DIR/libg2o.patch + sudo_apply_patch ${ROS_ROOT}/src/octomap_msgs/CMakeLists.txt $PATCH_FILES_DIR/octomap_msgs.patch makestamp ros_ws_deps else @@ -421,77 +436,20 @@ else fi ECHO_IN_BLUE "###############################################################\n" -ECHO_IN_BLUE "###############################################################" -ECHO_IN_BLUE ">> Remove useless ROS packages" -ECHO_IN_BLUE "###############################################################" -if [ $(checkstamp ros_deps_rm) = "false" ] ; then - rm -rf ~/ros_catkin_ws/src/gazebo_ros_pkgs/ - makestamp ros_deps_rm -else - SKIP_SECTION "Useless ROS packages already removed, skipping" -fi -ECHO_IN_BLUE "###############################################################\n" - -ECHO_IN_BLUE "###############################################################" -ECHO_IN_BLUE ">> Add missing ROS packages" -ECHO_IN_BLUE "###############################################################" -if [ $(checkstamp ros_deps_add) = "false" ] ; then - - cd ~/ros_catkin_ws/src - clone_git -b 1.0.1 https://github.com/GT-RAIL/rosauth.git - clone_git -b noetic-devel https://github.com/ros-drivers/rosserial.git - clone_git -b ros1 https://github.com/RobotWebTools/rosbridge_suite.git - clone_git -b noetic https://github.com/ccny-ros-pkg/imu_tools.git - clone_git --recursive https://github.com/orocos/orocos_kinematics_dynamics.git - - clone_git -b 0.21.1-noetic https://github.com/introlab/rtabmap_ros.git - clone_git -b noetic-devel https://github.com/ros-planning/navigation.git - - clone_git -b kinetic-devel https://github.com/pal-robotics/ddynamic_reconfigure.git - clone_git -b 2.3.2 https://github.com/IntelRealSense/realsense-ros.git - clone_git https://github.com/OTL/cv_camera.git - clone_git -b 0.6.4-noetic https://github.com/introlab/find-object.git - - makestamp ros_deps_add -else - SKIP_SECTION "Missing ROS packages already added, skipping" -fi -ECHO_IN_BLUE "###############################################################\n" - -ECHO_IN_BLUE "###############################################################" -ECHO_IN_BLUE ">> Replace incomplete ROS packages" -ECHO_IN_BLUE "###############################################################" -if [ $(checkstamp ros_deps_replace) = "false" ] ; then - - cd ~/ros_catkin_ws/src - rm -rf geometry2 navigation_msgs vision_opencv image_common perception_pcl pcl_msgs image_transport_plugins - - clone_git -b noetic-devel https://github.com/ros/geometry2.git - clone_git -b ros1 https://github.com/ros-planning/navigation_msgs.git - clone_git -b noetic https://github.com/ros-perception/vision_opencv.git - clone_git -b noetic-devel https://github.com/ros-perception/image_common.git - - clone_git -b 1.7.1 https://github.com/ros-perception/perception_pcl.git - clone_git -b noetic-devel https://github.com/ros-perception/pcl_msgs.git - clone_git -b noetic-devel https://github.com/ros-perception/image_transport_plugins.git - - cd ~/ros_catkin_ws - rosdep install --from-paths ./src/image_transport_plugins --ignore-packages-from-source --rosdistro noetic -y - - makestamp ros_deps_replace -else - SKIP_SECTION "Incomplete ROS packages already replaced, skipping" -fi -ECHO_IN_BLUE "###############################################################\n" - ECHO_IN_BLUE "###############################################################" ECHO_IN_BLUE ">> Build ROS workspace" ECHO_IN_BLUE "###############################################################" if [ $(checkstamp ros_ws_build) = "false" ] ; then - cd ~/ros_catkin_ws - apt list --installed | grep --quiet --no-messages --fixed-regexp "python3.9/" && sudo apt autoremove -y python3.9 || true - catkin config --init --install --space-suffix _isolated --cmake-args -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-march=native -ffast-math" -DCMAKE_C_FLAGS="-march=native -ffast-math" -DPYTHON_EXECUTABLE=/usr/bin/python3 -DCATKIN_ENABLE_TESTING=0 -Wno-dev - catkin build + cd ${ROS_ROOT} + + add_to_root_bashrc 'export PATH=/usr/local/cuda-11.4/bin:$PATH' + add_to_root_bashrc 'export LD_LIBRARY_PATH=/usr/local/cuda-11.4/lib64:$LD_LIBRARY_PATH' + + export ROS_VERSION=2 + sudo bash -c "export PATH=/usr/local/cuda-11.4/bin:$PATH; \ + export LD_LIBRARY_PATH=/usr/local/cuda-11.4/lib64:$LD_LIBRARY_PATH; \ + colcon build \ + --cmake-args -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-march=native -ffast-math" -DCMAKE_C_FLAGS="-march=native -ffast-math" -DCMAKE_PREFIX_PATH=$ROS_ROOT -DBUILD_WITH_CUDA=true -DBUILD_TESTING=OFF" makestamp ros_ws_build else @@ -502,7 +460,7 @@ ECHO_IN_BLUE "###############################################################\n" ECHO_IN_BLUE "###############################################################" ECHO_IN_BLUE ">> Add ROS setup source to .bashrc" ECHO_IN_BLUE "###############################################################" -add_to_bashrc 'source ~/ros_catkin_ws/install_isolated/setup.bash' +add_to_bashrc 'source /opt/ros/humble/install/setup.bash' ECHO_IN_BLUE "###############################################################\n" ECHO_IN_BLUE "###############################################################" @@ -553,7 +511,11 @@ ECHO_IN_BLUE "###############################################################" ECHO_IN_BLUE ">> Install ONNX Runtime" ECHO_IN_BLUE "###############################################################" if [ $(checkstamp onnxruntime) = "false" ] ; then + add_to_bashrc 'export PATH=/usr/local/cuda-11.4/bin:$PATH' + add_to_bashrc 'export LD_LIBRARY_PATH=/usr/local/cuda-11.4/lib64:$LD_LIBRARY_PATH' + sudo -H pip3 install packaging==23.1 + mkdir -p ~/deps cd ~/deps clone_git --depth 1 -b v1.14.1 https://github.com/microsoft/onnxruntime.git --recurse-submodule cd onnxruntime @@ -677,14 +639,13 @@ if [ $(checkstamp pytorch) = "false" ] ; then cd ~/deps clone_git --depth 1 -b v0.12.0 https://github.com/pytorch/audio.git --recurse-submodule cd audio - add_to_root_bashrc 'export PATH=/usr/local/cuda-11.4/bin:$PATH' - add_to_root_bashrc 'export LD_LIBRARY_PATH=/usr/local/cuda-11.4/lib64:$LD_LIBRARY_PATH' sudo -H pip3 install kaldi_io==0.9.5 sudo -H bash -c 'TORCH_CUDA_ARCH_LIST="7.2;8.7" CUDACXX=/usr/local/cuda/bin/nvcc python3 setup.py install' cd ~/deps clone_git https://github.com/NVIDIA-AI-IOT/torch2trt.git cd torch2trt + git checkout 36656b614f3fbc067ac673932e2200d7afdae712 sudo -H python3 setup.py install --plugins makestamp pytorch @@ -697,9 +658,9 @@ ECHO_IN_BLUE "###############################################################" ECHO_IN_BLUE ">> Install OpenTera-WebRTC ROS Python dependencies" ECHO_IN_BLUE "###############################################################" if [ $(checkstamp opentera_deps) = "false" ] ; then - cd $TTOP_REPO_PATH/ros/opentera-webrtc-ros/opentera_client_ros + cd $TTOP_REPO_PATH/ros/utils/opentera-webrtc-ros/opentera_client_ros sudo -H pip3 install -r requirements.txt - cd $TTOP_REPO_PATH/ros/opentera-webrtc-ros/opentera_webrtc_ros + cd $TTOP_REPO_PATH/ros/utils/opentera-webrtc-ros/opentera_webrtc_ros sudo -H pip3 install -r requirements.txt makestamp opentera_deps @@ -743,9 +704,11 @@ ECHO_IN_BLUE "###############################################################" if [ $(checkstamp ttop_ws_build) = "false" ] ; then source ~/.bashrc cd $TTOP_REPO_PATH/../.. - catkin config --init --cmake-args -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-march=native -ffast-math" -DCMAKE_C_FLAGS="-march=native -ffast-math" -DPYTHON_EXECUTABLE=/usr/bin/python3 -DCMAKE_WARN_DEPRECATED=OFF -DCMAKE_EXPORT_COMPILE_COMMANDS=ON - catkin config --profile release --init --space-suffix _release --cmake-args -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-march=native -ffast-math" -DCMAKE_C_FLAGS="-march=native -ffast-math" -DPYTHON_EXECUTABLE=/usr/bin/python3 -DCMAKE_WARN_DEPRECATED=OFF -DCMAKE_EXPORT_COMPILE_COMMANDS=ON - catkin build + + mkdir -p ~/.colcon + cp $SETUP_SCRIPTS_DIR/files/colcon_defaults.yaml $TTOP_REPO_PATH/../../colcon_defaults.yaml + + colcon build makestamp ttop_ws_build else diff --git a/tools/setup_scripts/patch/installLibrealsense.patch b/tools/setup_scripts/patch/installLibrealsense.patch deleted file mode 100644 index dd66775d..00000000 --- a/tools/setup_scripts/patch/installLibrealsense.patch +++ /dev/null @@ -1,18 +0,0 @@ -@@ -4,7 +4,7 @@ - # MIT License - - LIBREALSENSE_DIRECTORY=${HOME}/librealsense --LIBREALSENSE_VERSION=v2.17.1 -+LIBREALSENSE_VERSION=v2.50.0 - INSTALL_DIR=$PWD - - -@@ -94,7 +94,7 @@ - echo "${green}Configuring Make system${reset}" - # Use the CMake version that we built, must be > 3.8 - # Build with CUDA (default), the CUDA flag is USE_CUDA, ie -DUSE_CUDA=true --cmake ../ -DBUILD_EXAMPLES=true -DBUILD_WITH_CUDA=true -+cmake ../ -DCMAKE_CXX_FLAGS="-march=native -ffast-math" -DCMAKE_C_FLAGS="-march=native -ffast-math" -DBUILD_EXAMPLES=false -DBUILD_WITH_CUDA=true -DFORCE_RSUSB_BACKEND=true - # The library will be installed in /usr/local/lib, header files in /usr/local/include - # The demos, tutorials and tests will located in /usr/local/bin. - echo "${green}Building librealsense, headers, tools and demos${reset}" diff --git a/tools/setup_scripts/patch/libg2o.patch b/tools/setup_scripts/patch/libg2o.patch new file mode 100644 index 00000000..946c8d8f --- /dev/null +++ b/tools/setup_scripts/patch/libg2o.patch @@ -0,0 +1,162 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 0f754ff..7bf945c 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1,16 +1,17 @@ + cmake_minimum_required(VERSION 3.14) + set(CMAKE_LEGACY_CYGWIN_WIN32 0) + +-project(g2o) ++project(libg2o) ++find_package(ament_cmake REQUIRED) + + include(CPack) + include(GNUInstallDirs) + + # The library prefix +-set(LIB_PREFIX g2o_) ++set(LIB_PREFIX libg2o_) + +-set(g2o_C_FLAGS) +-set(g2o_CXX_FLAGS) ++set(libg2o_C_FLAGS) ++set(libg2o_CXX_FLAGS) + + # default built type + if(NOT CMAKE_BUILD_TYPE) +@@ -61,15 +62,15 @@ if(APPLE) + endif(APPLE) + + # Set the output directory for the build executables and libraries +-set(g2o_RUNTIME_OUTPUT_DIRECTORY ${g2o_SOURCE_DIR}/bin CACHE PATH "Target for the binaries") ++set(g2o_RUNTIME_OUTPUT_DIRECTORY ${libg2o_SOURCE_DIR}/bin CACHE PATH "Target for the binaries") + if(WIN32) +- set(g2o_LIBRARY_OUTPUT_DIRECTORY ${g2o_SOURCE_DIR}/bin CACHE PATH "Target for the libraries") ++ set(g2o_LIBRARY_OUTPUT_DIRECTORY ${libg2o_SOURCE_DIR}/bin CACHE PATH "Target for the libraries") + else(WIN32) +- set(g2o_LIBRARY_OUTPUT_DIRECTORY ${g2o_SOURCE_DIR}/lib CACHE PATH "Target for the libraries") ++ set(g2o_LIBRARY_OUTPUT_DIRECTORY ${libg2o_SOURCE_DIR}/lib CACHE PATH "Target for the libraries") + endif(WIN32) +-set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${g2o_LIBRARY_OUTPUT_DIRECTORY}) +-set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${g2o_LIBRARY_OUTPUT_DIRECTORY}) +-set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${g2o_RUNTIME_OUTPUT_DIRECTORY}) ++set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${libg2o_LIBRARY_OUTPUT_DIRECTORY}) ++set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${libg2o_LIBRARY_OUTPUT_DIRECTORY}) ++set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${libg2o_RUNTIME_OUTPUT_DIRECTORY}) + + # Set standard installation directories + set(RUNTIME_DESTINATION ${CMAKE_INSTALL_BINDIR}) +@@ -80,7 +81,7 @@ set(INCLUDES_INSTALL_DIR ${INCLUDES_DESTINATION}/g2o) + + # Set search directory for looking for our custom CMake scripts to + # look for SuiteSparse, QGLViewer, and Eigen3. +-list(APPEND CMAKE_MODULE_PATH ${g2o_SOURCE_DIR}/cmake_modules) ++list(APPEND CMAKE_MODULE_PATH ${libg2o_SOURCE_DIR}/cmake_modules) + + # Detect OS and define macros appropriately + if(WIN32) +@@ -157,8 +158,8 @@ if(G2O_USE_OPENMP) + find_package(OpenMP) + if(OPENMP_FOUND) + set (G2O_OPENMP 1) +- set(g2o_C_FLAGS "${g2o_C_FLAGS} ${OpenMP_C_FLAGS}") +- set(g2o_CXX_FLAGS "${g2o_CXX_FLAGS} -DEIGEN_DONT_PARALLELIZE ${OpenMP_CXX_FLAGS}") ++ set(libg2o_C_FLAGS "${libg2o_C_FLAGS} ${OpenMP_C_FLAGS}") ++ set(libg2o_CXX_FLAGS "${libg2o_CXX_FLAGS} -DEIGEN_DONT_PARALLELIZE ${OpenMP_CXX_FLAGS}") + message(STATUS "Compiling with OpenMP support") + endif(OPENMP_FOUND) + endif(G2O_USE_OPENMP) +@@ -358,8 +359,8 @@ endif() + option(BUILD_CODE_COVERAGE "Enable coverage reporting" OFF) + if(BUILD_CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + message(STATUS "Enabling coverage compiler flags") +- set(g2o_C_FLAGS "${g2o_C_FLAGS} --coverage") +- set(g2o_CXX_FLAGS "${g2o_CXX_FLAGS} --coverage") ++ set(libg2o_C_FLAGS "${libg2o_C_FLAGS} --coverage") ++ set(libg2o_CXX_FLAGS "${libg2o_CXX_FLAGS} --coverage") + endif() + + # Compiler specific options for gcc +@@ -390,8 +391,8 @@ if(CMAKE_COMPILER_IS_GNUCXX) + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -march=native") + endif() + # activate warnings !!! +- set(g2o_C_FLAGS "${g2o_C_FLAGS} -Wall -W") +- set(g2o_CXX_FLAGS "${g2o_CXX_FLAGS} -Wall -W") ++ set(libg2o_C_FLAGS "${libg2o_C_FLAGS} -Wall -W") ++ set(libg2o_CXX_FLAGS "${libg2o_CXX_FLAGS} -Wall -W") + endif(CMAKE_COMPILER_IS_GNUCXX) + + if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") +@@ -409,11 +410,11 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + endif() + + # activate all warnings +- #set(g2o_C_FLAGS "${g2o_C_FLAGS} -Weverything") +- #set(g2o_CXX_FLAGS "${g2o_CXX_FLAGS} -Weverything") +- set(g2o_C_FLAGS "${g2o_C_FLAGS} -Wall") +- set(g2o_CXX_FLAGS "${g2o_CXX_FLAGS} -Wall") +- #set(g2o_CXX_FLAGS "${g2o_CXX_FLAGS} -Wall -stdlib=libc++") ++ #set(libg2o_C_FLAGS "${libg2o_C_FLAGS} -Weverything") ++ #set(libg2o_CXX_FLAGS "${libg2o_CXX_FLAGS} -Weverything") ++ set(libg2o_C_FLAGS "${libg2o_C_FLAGS} -Wall") ++ set(libg2o_CXX_FLAGS "${libg2o_CXX_FLAGS} -Wall") ++ #set(libg2o_CXX_FLAGS "${libg2o_CXX_FLAGS} -Wall -stdlib=libc++") + endif() + + if(MSVC) +@@ -477,8 +478,8 @@ set(CMAKE_CXX_STANDARD 14) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + + # specifying compiler flags +-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${g2o_CXX_FLAGS}") +-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${g2o_C_FLAGS}") ++set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${libg2o_CXX_FLAGS}") ++set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${libg2o_C_FLAGS}") + + # Find Eigen3. If it defines the target, this is used. If not, + # fall back to the using the module form. +@@ -491,7 +492,7 @@ else() + endif () + + # Set up the top-level include directories +-include_directories(${g2o_SOURCE_DIR} ${PROJECT_BINARY_DIR}) ++include_directories(${libg2o_SOURCE_DIR} ${PROJECT_BINARY_DIR}) + + # Generate config.h + set(G2O_OPENGL_FOUND ${OPENGL_FOUND}) +@@ -503,11 +504,11 @@ set(G2O_CXX_COMPILER "${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER}") + + # Generate cmake configuration scripts + set(G2O_GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") +-set(G2O_VERSION_CONFIG "${G2O_GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake") +-set(G2O_PROJECT_CONFIG "${G2O_GENERATED_DIR}/${PROJECT_NAME}Config.cmake") +-set(G2O_TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") +-set(G2O_CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}") +-set(G2O_NAMESPACE "${PROJECT_NAME}::") ++set(G2O_VERSION_CONFIG "${G2O_GENERATED_DIR}/g2oConfigVersion.cmake") ++set(G2O_PROJECT_CONFIG "${G2O_GENERATED_DIR}/g2oConfig.cmake") ++set(G2O_TARGETS_EXPORT_NAME "g2oTargets") ++set(G2O_CONFIG_INSTALL_DIR "lib/cmake/g2o") ++set(G2O_NAMESPACE "g2o::") + set(G2O_SRC_DIR "${PROJECT_SOURCE_DIR}") + set(G2O_VERSION 1.0.0) + +@@ -519,8 +520,8 @@ WRITE_BASIC_PACKAGE_VERSION_FILE( + configure_file(config.h.in "${PROJECT_BINARY_DIR}/g2o/config.h") + install(FILES ${PROJECT_BINARY_DIR}/g2o/config.h DESTINATION ${INCLUDES_DESTINATION}/g2o) + +-configure_file("${g2o_SOURCE_DIR}/cmake_modules/Config.cmake.in" "${G2O_PROJECT_CONFIG}" @ONLY) +-configure_file("${g2o_SOURCE_DIR}/script/codecov.sh.in" "${CMAKE_CURRENT_BINARY_DIR}/codecov.sh" @ONLY) ++configure_file("${libg2o_SOURCE_DIR}/cmake_modules/Config.cmake.in" "${G2O_PROJECT_CONFIG}" @ONLY) ++configure_file("${libg2o_SOURCE_DIR}/script/codecov.sh.in" "${CMAKE_CURRENT_BINARY_DIR}/codecov.sh" @ONLY) + + install( + FILES "${G2O_PROJECT_CONFIG}" "${G2O_VERSION_CONFIG}" +@@ -551,3 +552,5 @@ endif() + + # Include the subdirectories + add_subdirectory(g2o) ++ ++ament_package() + diff --git a/tools/setup_scripts/patch/octomap_msgs.patch b/tools/setup_scripts/patch/octomap_msgs.patch new file mode 100644 index 00000000..c12e0732 --- /dev/null +++ b/tools/setup_scripts/patch/octomap_msgs.patch @@ -0,0 +1,10 @@ +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -36,7 +36,7 @@ rosidl_generate_interfaces(${PROJECT_NAME} + ) + + install(DIRECTORY include/ +- DESTINATION include ++ DESTINATION include/${PROJECT_NAME} + FILES_MATCHING PATTERN "*.h" + PATTERN ".svn" EXCLUDE) diff --git a/tools/setup_scripts/ros2_humble_install.sh b/tools/setup_scripts/ros2_humble_install.sh new file mode 100755 index 00000000..a9bebac4 --- /dev/null +++ b/tools/setup_scripts/ros2_humble_install.sh @@ -0,0 +1,252 @@ +#!/usr/bin/env bash +# this script builds a ROS2 distribution from source +# ROS_DISTRO, ROS_ROOT, ROS_PACKAGE environment variables should be set +export ROS_DISTRO=humble +export ROS_PACKAGE=desktop_full +export ROS_ROOT=/opt/ros/$ROS_DISTRO +export ROS_PYTHON_VERSION=3 +export DEBIAN_FRONTEND=noninteractive +export PYTHONIOENCODING=utf-8 +export ROS_VERSION=2 + +# Required for jetpack to find cuda +export PATH=/usr/local/cuda-11.4/bin:$PATH +export LD_LIBRARY_PATH=/usr/local/cuda-11.4/lib64:$LD_LIBRARY_PATH + +SCRIPT=`realpath $0` +SCRIPT_PATH=`dirname $SCRIPT` + +# set Python3 as default +update-alternatives --install /usr/bin/python python /usr/bin/python3 1 + +echo "ROS2 builder => ROS_DISTRO=$ROS_DISTRO ROS_PACKAGE=$ROS_PACKAGE ROS_ROOT=$ROS_ROOT" +set -e +#set -x + +# add the ROS deb repo to the apt sources list +apt-get update +apt-get install -y --no-install-recommends \ + curl \ + wget \ + gnupg2 \ + lsb-release \ + ca-certificates \ + git \ + libgtk-3-dev \ + libglfw3-dev \ + libgl1-mesa-dev \ + libglu1-mesa-dev \ + build-essential \ + cmake \ + cmake-curses-gui \ + libssl-dev \ + libusb-1.0-0-dev \ + libudev-dev \ + pkg-config + +curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/ros2.list > /dev/null +apt-get update + +# install development packages +apt-get install -y --no-install-recommends \ + build-essential \ + cmake \ + git \ + libbullet-dev \ + libpython3-dev \ + python3-colcon-common-extensions \ + python3-flake8 \ + python3-pip \ + python3-numpy \ + python3-pytest-cov \ + python3-rosdep \ + python3-setuptools \ + python3-vcstool \ + python3-rosinstall-generator \ + libasio-dev \ + libtinyxml2-dev \ + libcunit1-dev + +# install some pip packages needed for testing +pip3 install --upgrade --no-cache-dir \ + argcomplete \ + flake8-blind-except \ + flake8-builtins \ + flake8-class-newline \ + flake8-comprehensions \ + flake8-deprecated \ + flake8-docstrings \ + flake8-import-order \ + flake8-quotes \ + pytest-repeat \ + pytest-rerunfailures \ + pytest + +# upgrade cmake - https://stackoverflow.com/a/56690743 +# this is needed to build some of the ROS2 packages +# use pip to upgrade cmake instead because of kitware's rotating GPG keys: +# https://github.com/dusty-nv/jetson-containers/issues/216 +python3 -m pip install --upgrade pip +pip3 install --no-cache-dir scikit-build +pip3 install --upgrade --no-cache-dir --verbose cmake==3.22.1 +cmake --version +which cmake + +# remove other versions of Python3 +# workaround for 'Could NOT find Python3 (missing: Python3_NumPy_INCLUDE_DIRS Development' +apt purge -y python3.9 libpython3.9* || echo "python3.9 not found, skipping removal" +ls -ll /usr/bin/python* + +# create the ROS_ROOT directory +mkdir -p ${ROS_ROOT}/src +cd ${ROS_ROOT} + +# download ROS sources +# https://answers.ros.org/question/325245/minimal-ros2-installation/?answer=325249#post-id-325249 +rosinstall_generator --deps --rosdistro ${ROS_DISTRO} ${ROS_PACKAGE} \ + launch_xml \ + launch_yaml \ + launch_testing \ + launch_testing_ament_cmake \ + demo_nodes_cpp \ + demo_nodes_py \ + example_interfaces \ + camera_calibration_parsers \ + camera_info_manager \ + cv_bridge \ + v4l2_camera \ + vision_opencv \ + vision_msgs \ + image_geometry \ + image_pipeline \ + image_transport \ + compressed_image_transport \ + compressed_depth_image_transport \ + rosbag2_storage_mcap \ + rtabmap \ + rtabmap_ros \ + diagnostics \ + imu_tools \ + rosbridge_suite \ + tf_transformations \ + joint_state_publisher_gui \ + rqt_tf_tree \ +> ros2.${ROS_DISTRO}.${ROS_PACKAGE}.rosinstall +cat ros2.${ROS_DISTRO}.${ROS_PACKAGE}.rosinstall + +# Test if ros2.${ROS_DISTRO}.${ROS_PACKAGE}.rosinstall.vcsupdate exists if so run vcs pull src otherwise import src +if [ -f src/ros2.${ROS_DISTRO}.${ROS_PACKAGE}.rosinstall.vcsupdate ]; then + echo "vcs pull src" + vcs pull src +else + echo "vcs import --retry 100 src < ros2.${ROS_DISTRO}.${ROS_PACKAGE}.rosinstall" + vcs import --retry 100 src < ros2.${ROS_DISTRO}.${ROS_PACKAGE}.rosinstall +fi + +touch src/ros2.${ROS_DISTRO}.${ROS_PACKAGE}.rosinstall.vcsupdate + +# https://github.com/dusty-nv/jetson-containers/issues/181 +# rm -r ${ROS_ROOT}/src/ament_cmake +# git -C ${ROS_ROOT}/src/ clone https://github.com/ament/ament_cmake -b ${ROS_DISTRO} + +# remove librealsense2 & realsense-ros +#if [ -d "${ROS_ROOT}/src/librealsense2" ]; then +# rm -r ${ROS_ROOT}/src/librealsense2 +#fi + +#if [ -d "${ROS_ROOT}/src/realsense2_camera" ]; then +# rm -r ${ROS_ROOT}/src/realsense2_camera +#fi + +# skip installation of some conflicting packages # add librealsense2 +SKIP_KEYS="libopencv-dev libopencv-contrib-dev libopencv-imgproc-dev python-opencv python3-opencv xsimd xtensor xtl" + +# patches for building Humble on 18.04 +if [ "$ROS_DISTRO" = "humble" ] || [ "$ROS_DISTRO" = "iron" ] && [ $(lsb_release --codename --short) = "bionic" ]; then + # rti_connext_dds_cmake_module: No definition of [rti-connext-dds-6.0.1] for OS version [bionic] + SKIP_KEYS="$SKIP_KEYS rti-connext-dds-6.0.1 ignition-cmake2 ignition-math6" + + # the default gcc-7 is too old to build humble + apt-get install -y --no-install-recommends gcc-8 g++-8 + export CC="/usr/bin/gcc-8" + export CXX="/usr/bin/g++-8" + echo "CC=$CC CXX=$CXX" + + # upgrade pybind11 + apt-get purge -y pybind11-dev + pip3 install --upgrade --no-cache-dir pybind11-global + + # https://github.com/dusty-nv/jetson-containers/issues/160#issuecomment-1429572145 + git -C /tmp clone -b yaml-cpp-0.6.0 https://github.com/jbeder/yaml-cpp.git + cmake -S /tmp/yaml-cpp -B /tmp/yaml-cpp/BUILD -DBUILD_SHARED_LIBS=ON + cmake --build /tmp/yaml-cpp/BUILD --parallel $(nproc --ignore=1) + cmake --install /tmp/yaml-cpp/BUILD + rm -rf /tmp/yaml-cpp +fi + +echo "--skip-keys $SKIP_KEYS" + +# install dependencies using rosdep +# rosdep init +rosdep update +rosdep install -y \ + --ignore-src \ + --from-paths src \ + --rosdistro ${ROS_DISTRO} \ + --skip-keys "$SKIP_KEYS" + +# install xtl +if [ ! -d "${ROS_ROOT}/src/xtl" ]; then + cd ${ROS_ROOT}/src + git clone -b 0.7.0 https://github.com/xtensor-stack/xtl.git --depth 1 --recurse-submodules +fi + +# install xsimd +if [ ! -d "${ROS_ROOT}/src/xsimd" ]; then + cd ${ROS_ROOT}/src + git clone -b 7.4.8 https://github.com/xtensor-stack/xsimd.git --depth 1 --recurse-submodules +fi + +# install xtensor +if [ ! -d "${ROS_ROOT}/src/xtensor" ]; then + cd ${ROS_ROOT}/src + git clone -b 0.23.10 https://github.com/xtensor-stack/xtensor --depth 1 --recurse-submodules +fi + +# install librealsense with CUDA support +# if [ ! -d "/tmp/librealsense" ]; then +# cd /tmp +# git clone https://github.com/IntelRealSense/librealsense.git -b v2.55.1 --depth 1 --recurse-submodules +# mkdir -p /tmp/librealsense/build +# cd /tmp/librealsense/build +# cmake ../ -DCMAKE_CXX_FLAGS="-march=native -ffast-math" -DCMAKE_C_FLAGS="-march=native -ffast-math" -DBUILD_EXAMPLES=false -DBUILD_WITH_CUDA=true -DCMAKE_INSTALL_PREFIX=$ROS_ROOT +# cmake --build . --parallel $(nproc --ignore=1) +# cmake --install . +#fi + +# clone the realsense-ros package in the src +#if [ ! -d "${ROS_ROOT}/src/realsense-ros" ]; then +# git -C ${ROS_ROOT}/src clone -b 4.55.1 https://github.com/IntelRealSense/realsense-ros.git --depth 1 --recurse-submodules +#fi + +# clone cv_camera package in the src +if [ ! -d "${ROS_ROOT}/src/cv_camera" ]; then + git -C ${ROS_ROOT}/src clone -b master https://github.com/Kapernikov/cv_camera.git --depth 1 --recurse-submodules +fi + +cd ${ROS_ROOT} + +# Apply the patch of libg2o +sudo patch -u ${ROS_ROOT}/src/libg2o/CMakeLists.txt $SCRIPT_PATH/patch/libg2o.patch +sudo patch -u ${ROS_ROOT}/src/octomap_msgs/CMakeLists.txt $SCRIPT_PATH/patch/octomap_msgs.patch + +# build the rest - for verbose, see https://answers.ros.org/question/363112/how-to-see-compiler-invocation-in-colcon-build +colcon build \ + --cmake-args -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-march=native -ffast-math" -DCMAKE_C_FLAGS="-march=native -ffast-math" -DCMAKE_PREFIX_PATH=$ROS_ROOT -DBUILD_WITH_CUDA=true -DBUILD_TESTING=OFF + +# remove build files +# rm -rf ${ROS_ROOT}/src +# rm -rf ${ROS_ROOT}/logs +# rm -rf ${ROS_ROOT}/build +# rm ${ROS_ROOT}/*.rosinstall