├── .dockerignore ├── .gitattributes ├── .github └── workflows │ └── python-ci.yaml ├── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── _deprecated ├── apyros │ ├── __init__.py │ ├── logio.py │ ├── manual.py │ ├── metalog.py │ ├── metaopen.py │ ├── sourcelogger.py │ ├── test_data │ │ ├── meta_160628_174658.log │ │ └── meta_170516_192926.log │ └── test_metalog.py ├── camera.py ├── can.py ├── canproxy.py ├── column.py ├── conda-linux.yml ├── conda-win32.yml ├── config │ ├── fill-pattern-15x5.json │ ├── mapit.json │ ├── navpat-default.json │ └── playground15x5.json ├── demo.py ├── demo2.py ├── demo_wall.py ├── driver.py ├── followme.py ├── gps.py ├── helloworld.py ├── helper.py ├── johndeere.py ├── laser.py ├── launcher.py ├── lib │ ├── __init__.py │ ├── camera_marks.py │ ├── config.py │ ├── landmarks.py │ ├── localization.py │ ├── processor.py │ ├── test_config.py │ ├── test_data │ │ └── playground12x5.json │ ├── test_landmarks.py │ └── test_localization.py ├── navpat.py ├── orchard.py ├── remote.py ├── ro.py ├── rr.py ├── s60 │ ├── ball.png │ └── md_ball.py ├── sdoplg.py ├── spider3.py ├── subt_graveyard │ ├── r2.json │ └── r2.launch ├── test_column.py ├── test_data │ └── roboorienteering │ │ ├── 2015 │ │ ├── Kolo0.dat │ │ ├── Kolo1.dat │ │ ├── Kolo2.dat │ │ └── Kolo3.dat │ │ └── 2016 │ │ ├── Kolo2.dat │ │ └── Kolo3.dat ├── tools │ ├── __init__.py │ ├── annot.py │ ├── filtration_select.py │ ├── logparser.py │ ├── logparser2.py │ ├── meta2view.py │ ├── parse_laserraw.py │ ├── plot.py │ ├── rosbag.py │ ├── throttle_view.py │ ├── viewer.py │ ├── zip2mkv.py │ └── zipit.py ├── velodyne.py └── webserver │ ├── README.md │ ├── controller.py │ ├── lights.html │ └── web2.py ├── config ├── bare-skiddy.json ├── cortexpilot-no-camera.json ├── cortexpilot-only.json ├── cortexpilot.json ├── deedee-demo.json ├── deedee-subt.json ├── dual-qorvo.json ├── eduro-followme-dual-uwb.json ├── eduro-followme-uwb.json ├── eduro-followme-vanjee.json ├── eduro-followme.json ├── eduro-followpath.json ├── eduro-go-vanjee.json ├── eduro-go.json ├── eduro-ro2019-lord.json ├── eduro-ro2019.json ├── eduro-subt-estop-lora-wifi-jetson.json ├── eduro-subt-estop-lora-wifi.json ├── eduro-subt-estop-lora.json ├── eduro-subt-estop.json ├── eduro-subt.json ├── eduro-two-lidars.json ├── eduro.json ├── explore-left-wall.json ├── explore-right-wall.json ├── fr07-followpath.json ├── fr07-go.json ├── gps-mpfc-linux.json ├── gps-pozyx.json ├── jetson-node-k2-front.json ├── jetson-node-k2-rear.json ├── kloubak-slot.json ├── kloubak2-subt-estop-lora-jetson.json ├── kloubak2-subt-estop-lora.json ├── kloubak3-no-sensors.json ├── kloubak3-subt-estop-lora-jetson.json ├── kloubak3-subt-estop-lora.json ├── maria-realsense.json ├── maria-ros.json ├── maria.json ├── matty-go.json ├── mobos-ros.json ├── myrobot-lora.json ├── oak-cone-detection.json ├── pcan-kloubak.json ├── pozyx-io.json ├── ro2018-czu-waypoints.json ├── ro2018-simulation.json ├── ro2018-spider-gps-imu.json ├── ro2019-waypoints.json ├── robik-subt-estop.json ├── skiddy-subt-serialloop.json ├── skiddy-subt.json ├── spider-camera.json ├── spider-rtk.json ├── spider-velodyne.json ├── spider.json ├── subt-e-stop-windows-A24.json ├── subt-e-stop-windows.json ├── test-apriltag-rs.json ├── test-canserial.json ├── test-dual-timer.json ├── test-estop.json ├── test-eth-gps-bridge.json ├── test-eth-gps.json ├── test-eth-imu.json ├── test-fr07.json ├── test-fusion.json ├── test-gas-detector.json ├── test-gps-imu.json ├── test-ip-camera.json ├── test-jetson_artf_node.json ├── test-lidar-tim571.json ├── test-lora-windows.json ├── test-lora.json ├── test-lord-imu-linux.json ├── test-lord-imu.json ├── test-matty.json ├── test-o3d3xx.json ├── test-oak-camera-usb.json ├── test-oak-camera.json ├── test-oak-sr-usb.json ├── test-opencv-camera.json ├── test-ouster_lidar-udp.json ├── test-pcan.json ├── test-pozyx.json ├── test-pull_zmq.json ├── test-pulutof1.json ├── test-qorvo.json ├── test-realsense-D400.json ├── test-realsense-L500.json ├── test-realsense-T200.json ├── test-replay-node.json ├── test-robik.json ├── test-spider-gps-imu.json ├── test-spider.json ├── test-system-monitor.json ├── test-usb-camera.json ├── test-usb-lidar.json ├── test-vanjee-lidar.json ├── test-velodyne.json ├── test-vesc.json ├── test-wifiscan.json ├── test-windows-gps.json ├── test-winsen-gas-detector.json ├── test-zeromq.json └── zeromq-fwd.json ├── doc └── sphinx │ ├── Makefile │ ├── can.rst │ ├── conf.py │ ├── drivers.rst │ ├── eduro.rst │ ├── glossary.rst │ ├── index.rst │ ├── logging.rst │ ├── make.bat │ ├── msgtypes.rst │ └── rosproxy.rst ├── examples ├── README.md ├── accumulator │ ├── accumulator.json │ └── accumulator.py ├── demo │ ├── demo.py │ └── spider_demo.py ├── gym │ ├── configs │ │ ├── config_example_map.yaml │ │ ├── config_example_map2.yaml │ │ ├── example_map.png │ │ ├── example_map.yaml │ │ ├── example_map2.png │ │ ├── example_map2.yaml │ │ ├── race-config.json │ │ └── test-gym_simulation.json │ ├── gym_simulator.py │ └── my_race.py ├── myrobot │ ├── myapp.py │ ├── myrobot-slots.json │ ├── myrobot.json │ └── myrobot.py └── sick2018 │ ├── eduro-sick2018.json │ ├── scan_feature.py │ ├── sick2018.py │ └── test_scan_feature.py ├── moon ├── __init__.py ├── artifacts.py ├── bulk_test.sh ├── config │ ├── moon-excavator-round2.json │ ├── moon-hauler-round2.json │ ├── moon-round1.json │ └── moon-round3.json ├── controller.py ├── controller_excavator_round2.py ├── controller_hauler_round2.py ├── controller_round1.py ├── controller_round3.py ├── docker │ ├── build.bash │ └── rover │ │ ├── Dockerfile │ │ ├── entrypoint.bash │ │ ├── rosconsole.config │ │ └── run_solution.bash ├── howto.md ├── light_manager.py ├── monitors.py ├── moon-view.bat ├── moon-view.sh ├── moonnode.py ├── motorpid.py ├── odometry.py ├── ros_launchfiles │ ├── qual_round_1.launch │ ├── qual_round_2.launch │ └── qual_round_3.launch ├── rospy │ ├── rospy_base.py │ ├── rospy_excavator.py │ ├── rospy_excavator_round2.py │ ├── rospy_hauler.py │ ├── rospy_hauler_round2.py │ ├── rospy_round1.py │ ├── rospy_round2.py │ ├── rospy_round3.py │ ├── rospy_rover.py │ ├── rospy_scout.py │ ├── rospy_scout_round1.py │ └── rospy_scout_round3.py ├── test_artifacts.py ├── test_controller.py ├── test_controller_excavator_round2.py ├── test_controller_round1.py ├── test_controller_round3.py ├── test_data │ ├── basemarker.jpg │ └── cube_homebase.jpg ├── test_monitors.py ├── test_motorpid.py ├── test_odometry.py ├── vehicles │ ├── __init__.py │ ├── excavator.py │ ├── hauler.py │ ├── rover.py │ ├── scout.py │ └── test_rover.py └── xml │ ├── cubesat.xml │ └── homebase.xml ├── osgar ├── __init__.py ├── bus.py ├── drivers │ ├── __init__.py │ ├── canserial.py │ ├── cortexpilot.py │ ├── deedee.py │ ├── eduro.py │ ├── fusion.py │ ├── gas_detector.py │ ├── gps.py │ ├── imu.py │ ├── kloubak.py │ ├── logserial.py │ ├── logsocket.py │ ├── logusb.py │ ├── logzeromq.py │ ├── lora.py │ ├── lord_imu.py │ ├── maria.py │ ├── o3d3xx_camera.py │ ├── oak_camera.py │ ├── odoimuloc.py │ ├── opencv.py │ ├── ouster_lidar.py │ ├── pcan.py │ ├── pozyx.py │ ├── pull.py │ ├── push.py │ ├── qorvo.py │ ├── realsense.py │ ├── replay.py │ ├── resize.py │ ├── rosmsg.py │ ├── rtk_filter.py │ ├── sicklidar.py │ ├── simulator.py │ ├── spider.py │ ├── system_monitor.py │ ├── test_canserial.py │ ├── test_cortexpilot.py │ ├── test_eduro.py │ ├── test_gps.py │ ├── test_imu.py │ ├── test_kloubak.py │ ├── test_logserial.py │ ├── test_logsocket.py │ ├── test_logusb.py │ ├── test_logzeromq.py │ ├── test_lora.py │ ├── test_lord_imu.py │ ├── test_maria.py │ ├── test_oak_camera.py │ ├── test_odoimuloc.py │ ├── test_realsense.py │ ├── test_rosmsg.py │ ├── test_sicklidar.py │ ├── test_simulator.py │ ├── test_spider.py │ ├── test_system_monitor.py │ ├── test_vanjee.py │ ├── test_velodyne.py │ ├── test_winsen_gas_detector.py │ ├── timer.py │ ├── usbcam.py │ ├── vanjee.py │ ├── velodyne.py │ ├── vesc.py │ └── winsen_gas_detector.py ├── explore.py ├── followme.py ├── followme_uwb.py ├── followpath.py ├── go.py ├── gpsnav.py ├── launcher.py ├── lib │ ├── __init__.py │ ├── config.py │ ├── depth.py │ ├── icp.py │ ├── lidar_pts.py │ ├── line.py │ ├── local_planner.py │ ├── loop.py │ ├── mathex.py │ ├── pplanner.py │ ├── quaternion.py │ ├── route.py │ ├── serialize.py │ ├── test_config.py │ ├── test_depth.py │ ├── test_icp.py │ ├── test_lidar_pts.py │ ├── test_line.py │ ├── test_local_planner.py │ ├── test_loop.py │ ├── test_pplanner.py │ ├── test_quaternion.py │ ├── test_route.py │ ├── test_serialize.py │ ├── test_unittest.py │ ├── test_virtual_bumper.py │ ├── unittest.py │ └── virtual_bumper.py ├── logger.py ├── node.py ├── obstdet3d.py ├── platforms │ ├── __init__.py │ ├── matty.py │ ├── test_matty.py │ ├── test_yuhesen.py │ └── yuhesen.py ├── record.py ├── replay.py ├── ro2018.py ├── test_bus.py ├── test_explore.py ├── test_followme.py ├── test_followpath.py ├── test_go.py ├── test_logger.py ├── test_node.py ├── test_record.py ├── test_ro2018.py ├── test_zmqrouter.py ├── tools │ ├── README.md │ ├── __init__.py │ ├── calibfish.py │ ├── lidarview.py │ ├── log2apriltag.py │ ├── log2pcap.py │ ├── log2video.py │ ├── map3dview.py │ └── strip.py ├── turn.py └── zmqrouter.py ├── pyproject.toml ├── release.bat ├── requirements.txt ├── setup.py ├── subt ├── __init__.py ├── __main__.py ├── apriltag.py ├── artf_detector.py ├── artf_edgetpu_detector.py ├── artf_filter.py ├── artf_gas.py ├── artf_model.py ├── artf_node.py ├── artf_reporter.py ├── artf_utils.py ├── artifacts.py ├── aws2info.py ├── breadcrumbs.py ├── bundle_rgbd.py ├── check_gas.py ├── check_phone.py ├── cloudsim2osgar.py ├── config │ ├── coro_pam.json │ └── darpa-artf.csv ├── control_center_qt.py ├── crash_report.py ├── depth2scan.py ├── doc │ ├── narrative.md │ └── virtual-howto.md ├── docker │ ├── base │ │ ├── Dockerfile │ │ └── tags │ ├── build.bash │ ├── cudatest │ │ ├── Dockerfile │ │ ├── cloudsim_run.py │ │ ├── cudatest3.py │ │ └── cudatest_entrypoint.bash │ ├── gui │ │ ├── Dockerfile │ │ └── entrypoint.bash │ ├── loadtest │ │ ├── Dockerfile │ │ ├── loadtest_entrypoint.bash │ │ └── main.py │ ├── robotika │ │ ├── Dockerfile │ │ ├── Makefile │ │ ├── entrypoint.bash │ │ ├── python_logging.conf │ │ ├── rosconsole.config │ │ └── run_solution.bash │ ├── run.bash │ └── unittest │ │ ├── Dockerfile │ │ ├── run_solution.bash │ │ └── subt_seed_node.cc ├── drone.py ├── dummy_darpa_server.py ├── estop.py ├── gazebo_poses.py ├── ign.proto ├── ign_pb2.py ├── ign_poses.py ├── image_extractor.py ├── jetson_artf_node.py ├── launch.py ├── log2map.py ├── main.py ├── mapping_server.py ├── marsupial.py ├── multitrace.py ├── mytimer.py ├── name_decoder.py ├── octomap.json ├── octomap.py ├── points2scan.py ├── radio.py ├── report_artf.py ├── ros │ ├── __init__.py │ ├── base │ │ ├── CMakeLists.txt │ │ ├── __init__.py │ │ ├── custom_rosconsole.conf │ │ ├── launch │ │ │ └── base.launch │ │ ├── package.xml │ │ └── src │ │ │ ├── __init__.py │ │ │ ├── base_car.py │ │ │ ├── base_mob.py │ │ │ ├── base_transform.py │ │ │ ├── car_rotation.py │ │ │ ├── compass.py │ │ │ ├── gps_to_utc.py │ │ │ ├── motor_controller.py │ │ │ ├── pid.py │ │ │ ├── roboconfig_car.py │ │ │ ├── roboconfig_mob.py │ │ │ ├── robohw_real_car.py │ │ │ ├── robohw_real_mob.py │ │ │ ├── robomath.py │ │ │ └── virtual_bumper.py │ ├── proxy │ │ ├── CMakeLists.txt │ │ ├── artifact_type_from_string.cc │ │ ├── depth_filter.cc │ │ ├── flyability.cc │ │ ├── launch │ │ │ ├── sim.launch │ │ │ └── teambase.launch │ │ ├── package.xml │ │ ├── pose_from_artifact_origin.cc │ │ ├── pull.py │ │ ├── push.py │ │ ├── ros_proxy_node.cc │ │ ├── ros_proxy_teambase.cc │ │ ├── sendlog.py │ │ ├── traversability.cc │ │ └── wait.py │ ├── robot │ │ ├── CMakeLists.txt │ │ ├── __init__.py │ │ ├── custom_rosconsole.conf │ │ ├── default.rviz │ │ ├── launch │ │ │ ├── auto_car.launch │ │ │ ├── auto_mob.launch │ │ │ ├── coro_pam.launch │ │ │ ├── deedee.launch │ │ │ ├── drone_keyboard.launch │ │ │ ├── eduro.launch │ │ │ ├── freyja.launch │ │ │ ├── joystick.launch │ │ │ ├── k2-virt.launch │ │ │ ├── k2.launch │ │ │ ├── k3.launch │ │ │ ├── maria.launch │ │ │ ├── skiddy.launch │ │ │ ├── straight.launch │ │ │ └── x4.launch │ │ ├── maps │ │ │ ├── jenstejn.osm │ │ │ └── jenstejn_small.osm │ │ ├── package.xml │ │ ├── params_car │ │ │ ├── base_local_planner_DWA_params.yaml │ │ │ ├── base_local_planner_params.yaml │ │ │ ├── camera_calibration.yaml │ │ │ ├── costmap_common_params.yaml │ │ │ ├── ekf_params.yaml │ │ │ ├── global_costmap_params.yaml │ │ │ ├── local_costmap_params.yaml │ │ │ ├── navsat_params.yaml │ │ │ └── ublox.yaml │ │ ├── params_common │ │ │ ├── base_local_planner_params.yaml │ │ │ ├── camera_calibration.yaml │ │ │ ├── costmap_common_params.yaml │ │ │ ├── d435i.json │ │ │ ├── ekf_params.yaml │ │ │ ├── global_costmap_params.yaml │ │ │ ├── local_costmap_params.yaml │ │ │ └── move_base_params.yaml │ │ ├── params_eduro │ │ │ ├── cliff_detector_params.yaml │ │ │ └── depth_scan_params.yaml │ │ ├── params_k2 │ │ │ ├── cliff_detector_params.yaml │ │ │ └── depth_scan_params.yaml │ │ ├── params_maria │ │ │ ├── cliff_detector_params.yaml │ │ │ └── depth_scan_params.yaml │ │ ├── params_mob │ │ │ ├── base_local_planner_params.yaml │ │ │ ├── camera_calibration.yaml │ │ │ ├── cliff_detector_params.yaml │ │ │ ├── costmap_common_params.yaml │ │ │ ├── depth_scan_params.yaml │ │ │ ├── ekf_params.yaml │ │ │ ├── global_costmap_params.yaml │ │ │ ├── local_costmap_params.yaml │ │ │ └── move_base_params.yaml │ │ ├── src │ │ │ ├── altitude_from_atmospheric_pressure.py │ │ │ ├── distmap_planner.py │ │ │ ├── drone_height.py │ │ │ ├── filter_depth.py │ │ │ ├── filter_pointcloud.py │ │ │ ├── globalmap_to_localmap.py │ │ │ ├── k2.py │ │ │ ├── laserscan_to_pointcloud.py │ │ │ ├── map_tf_broadcaster.py │ │ │ ├── map_to_scan.py │ │ │ ├── monocular_traversability.py │ │ │ ├── origin_tf.py │ │ │ ├── robomath.py │ │ │ ├── rospy_zmq.py │ │ │ ├── rotate_image_right.py │ │ │ └── voronoi_filter.py │ │ └── test │ │ │ ├── __init__.py │ │ │ └── test_filter_pointcloud.py │ └── straight_drive │ │ ├── CMakeLists.txt │ │ ├── launch │ │ └── straight_drive.launch │ │ ├── package.xml │ │ └── src │ │ └── straight_drive.py ├── rosbag2log.py ├── roslaunch.py ├── scan_mixer.py ├── script │ ├── bridge.bash │ ├── build-and-install-ros-packages.bash │ ├── check-artf.bat │ ├── check_rosK2.bash │ ├── check_rosK3.bash │ ├── debug-virtual-view.bat │ ├── devel.bash │ ├── eduro-view.bat │ ├── kloubak-view.bat │ ├── mobos-view.bat │ ├── rear-artf.bat │ ├── rear-k2-sensors.json │ ├── robik-view.bat │ ├── run_deedee.bash │ ├── run_eduro_ros.sh │ ├── run_jetson_front.bash │ ├── run_kloubak2.sh │ ├── run_kloubak2_jetson.sh │ ├── run_kloubak2_ros.sh │ ├── run_kloubak3.sh │ ├── run_kloubak3_ros.sh │ ├── run_maria.sh │ ├── run_mobos.sh │ ├── run_robotika_subt.sh │ ├── run_skiddy.bash │ ├── sim.bash │ ├── teleop.bash │ ├── vesc-odo.bat │ ├── virtual-depth-view.bat │ └── virtual-view.bat ├── serialloop.py ├── simulation.py ├── submission │ ├── cave-circuit.toml │ ├── finals.toml │ └── two-freyjas.toml ├── subt-freyja.json ├── subt-k2-virt.json ├── teambase.py ├── test_artf_filter.py ├── test_artf_gas.py ├── test_artf_node.py ├── test_artf_reporter.py ├── test_artifacts.py ├── test_breadcrumbs.py ├── test_crash_report.py ├── test_data │ ├── artf-electrical-box.jpg │ ├── artf-extinguisher-hd.jpg │ ├── artf-toolbox.jpg │ ├── artf-valve-hd.jpg │ ├── artf-valve2-hd.jpg │ ├── freyja-octomap.bin │ └── rgbd.npz ├── test_depth2scan.py ├── test_drone.py ├── test_dummy_darpa_server.py ├── test_image_extractor.py ├── test_launch.py ├── test_mapping_server.py ├── test_marsupial.py ├── test_multitrace.py ├── test_name_decoder.py ├── test_octomap.py ├── test_points2scan.py ├── test_radio.py ├── test_report_artf.py ├── test_scan_mixer.py ├── test_subt.py ├── test_teambase.py ├── test_trace.py ├── test_twistwrap.py ├── test_wifisignal.py ├── tf_detector.py ├── tools │ ├── __init__.py │ ├── allsync.py │ ├── analyze_detectors.py │ ├── artf2json.py │ ├── avi2jpg.py │ ├── draw_pos_data.py │ ├── draw_wifi.py │ ├── eduroview.py │ ├── ignstate.py │ ├── kloubakview.py │ ├── logschecker.py │ ├── mariaview.py │ ├── mobosview.py │ ├── run.py │ ├── startfile.py │ ├── submit.py │ ├── test_validator.py │ └── validator.py ├── trace.py ├── twistwrap.py ├── wifisignal.py ├── zmq-subt-teambase.json ├── zmq-subt-x2.json └── zmq-subt-x4.json └── test.py /.dockerignore: -------------------------------------------------------------------------------- 1 | # https://docs.docker.com/engine/reference/builder/#dockerignore-file 2 | 3 | # Byte-compiled / optimized / DLL files 4 | **/__pycache__/ 5 | **/*.py[cod] 6 | **/*$py.class 7 | 8 | # pycharm dir 9 | .idea 10 | 11 | # all log files anywhere 12 | **/*.log 13 | **/*.bag 14 | **/*.bag.active 15 | 16 | # created when using `pip install -e .` 17 | osgar.egg-info/ 18 | 19 | # other 20 | _deprecated 21 | subt/submission 22 | 23 | ign-logs 24 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | subt/ign_pb2.py linguist-generated -diff -merge 2 | -------------------------------------------------------------------------------- /.github/workflows/python-ci.yaml: -------------------------------------------------------------------------------- 1 | name: Python CI 2 | 3 | on: 4 | pull_request: 5 | 6 | jobs: 7 | test: 8 | runs-on: ${{ matrix.os }} 9 | strategy: 10 | fail-fast: false 11 | matrix: 12 | os: [ubuntu-22.04, windows-2022] 13 | python-version: ["3.8", "3.9", "3.10"] 14 | timeout-minutes: 5 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Set up Python ${{ matrix.python-version }} 18 | uses: actions/setup-python@v1 19 | with: 20 | python-version: ${{ matrix.python-version }} 21 | - name: Display Python version 22 | run: python -c "import sys; print(sys.version)" 23 | - name: Install dependencies 24 | run: | 25 | python -m pip install --upgrade pip 26 | pip install -r requirements.txt 27 | - name: Run tests 28 | run: | 29 | python -u test.py -v 30 | env: 31 | PYTHONIOENCODING: utf-8 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Python template 2 | # Byte-compiled / optimized / DLL files 3 | __pycache__/ 4 | *.py[cod] 5 | *$py.class 6 | 7 | # pycharm dir 8 | .idea 9 | 10 | # created when using `pip install -e .` 11 | osgar.egg-info/ 12 | 13 | # ignition simulation logs 14 | ign-logs/ 15 | 16 | # -*- mode: gitignore; -*- 17 | *~ 18 | \#*\# 19 | /.emacs.desktop 20 | /.emacs.desktop.lock 21 | *.elc 22 | auto-save-list 23 | tramp 24 | .\#* 25 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | How to contribute 2 | ================= 3 | 4 | * master has its history never changed (no rebase) and always works 5 | - compiles 6 | - all tests pass 7 | * all development is done on branches 8 | * all branches are based on master and all PRs are to master 9 | * branches and PRs are as contained and small as possible and reasonable 10 | * each PR is reviewed by a member of @robotika 11 | * before merging to master branches are squashed to cleanup the patchset to contain only relevant commits 12 | * before merging the branch is rebased onto master to create a simple history (easy to revert and bisect) 13 | 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 robotika.cz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /_deprecated/apyros/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotika/osgar/ab10ba4004329dcc0ea1ffc68ac2334bb1995c38/_deprecated/apyros/__init__.py -------------------------------------------------------------------------------- /_deprecated/apyros/manual.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | """ 3 | Manual control 4 | """ 5 | import sys 6 | 7 | 8 | class ManualControlException( Exception ): 9 | pass 10 | 11 | 12 | if sys.platform == 'win32': 13 | import msvcrt # for kbhit 14 | 15 | def myKbhit(): 16 | if not msvcrt.kbhit(): 17 | return 0 18 | key = msvcrt.getch() 19 | if key == '\xe0': # Arrows 20 | key = (key, msvcrt.getch()) 21 | return key 22 | 23 | else: 24 | # TODO if pygame is not available try linux io 25 | import pygame 26 | g_pygameWindow = None 27 | 28 | def myKbhit(): 29 | global g_pygameWindow 30 | if g_pygameWindow is None: 31 | pygame.init() 32 | g_pygameWindow = pygame.display.set_mode((100,100)) 33 | events = pygame.event.get() 34 | for event in events: 35 | if event.type == pygame.KEYDOWN: 36 | return 1 # or key value?? 37 | return 0 38 | 39 | 40 | if __name__ == "__main__": 41 | # for testing of myKbhit on various OS 42 | print("Press Any Key!") 43 | while not myKbhit(): 44 | pass 45 | print("Thank you") 46 | 47 | # vim: expandtab sw=4 ts=4 48 | 49 | -------------------------------------------------------------------------------- /_deprecated/apyros/metaopen.py: -------------------------------------------------------------------------------- 1 | """ 2 | only wrapper for ZIP files 3 | """ 4 | 5 | import os 6 | from zipfile import ZipFile 7 | 8 | 9 | def metaopen(filename, mode='r'): 10 | """Wrapper for opening files optionally from ZIP""" 11 | assert mode in ['r', 'rb'], mode # just to know what modes we use 12 | if '.zip' in filename: 13 | return ZipFile(os.path.dirname(filename)).open(os.path.basename(filename)) 14 | else: 15 | return open(filename, mode) 16 | # vim: expandtab sw=4 ts=4 17 | 18 | -------------------------------------------------------------------------------- /_deprecated/apyros/test_data/meta_160628_174658.log: -------------------------------------------------------------------------------- 1 | ['M:\\git\\ARDroneSDK3\\katarina\\demo.py', 'demo-takeoff-409600buf'] 2 | navdata: logs/navdata_160628_174658.bin 3 | cmd: logs/cmd_160628_174658.bin 4 | console: logs/console_160628_174658.txt 5 | now: datetime.datetime(2016, 6, 28, 17, 46, 58, 603000) 6 | -------------------------------------------------------------------------------- /_deprecated/apyros/test_data/meta_170516_192926.log: -------------------------------------------------------------------------------- 1 | ['./navpat.py', 'nesrandauz'] 2 | can: logs/can_170516_192926.log 3 | timestamps: logs/timestamps_170516_192926.log 4 | gps: logs/gps_170516_192931.log 5 | laser: logs/laser_170516_192931.log 6 | camera: logs/camera_170516_192931.log 7 | -------------------------------------------------------------------------------- /_deprecated/apyros/test_metalog.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from .metalog import * 3 | 4 | 5 | def test_data(filename): 6 | return os.path.join(os.path.dirname(__file__), 'test_data', filename) 7 | 8 | 9 | class MetaLogTest(unittest.TestCase): 10 | 11 | def test_missing_remission(self): 12 | ml = MetaLog(test_data('meta_170516_192926.log')) 13 | filename = ml.getLog('laser') 14 | self.assertIsNotNone(filename) # logs/laser_170516_192931.log 15 | filename = ml.getLog('remission') 16 | self.assertIsNone(filename) 17 | filename = ml.getLog('camera') 18 | self.assertIsNotNone(filename) # logs/camera_170516_192931.log 19 | 20 | def test_getlog_twice(self): 21 | ml = MetaLog(test_data('meta_170516_192926.log')) 22 | filename = ml.getLog('laser') 23 | self.assertIsNotNone(filename) # logs/laser_170516_192931.log 24 | filename = ml.getLog('laser') 25 | self.assertIsNone(filename) 26 | 27 | def test_now(self): 28 | ml = MetaLog(test_data('meta_160628_174658.log')) 29 | self.assertEqual(ml.now(), 30 | datetime.datetime(2016, 6, 28, 17, 46, 58, 603000)) 31 | self.assertIsNone(ml.now()) 32 | 33 | 34 | if __name__ == "__main__": 35 | unittest.main() 36 | 37 | # vim: expandtab sw=4 ts=4 38 | 39 | -------------------------------------------------------------------------------- /_deprecated/conda-linux.yml: -------------------------------------------------------------------------------- 1 | name: osgar 2 | channels: 3 | - conda-forge 4 | - defaults 5 | dependencies: 6 | - ca-certificates=2017.4.17=0 7 | - certifi=2017.4.17=py27_0 8 | - jasper=1.900.1=4 9 | - jpeg=9b=0 10 | - libpng=1.6.28=0 11 | - libtiff=4.0.6=7 12 | - ncurses=5.9=10 13 | - opencv=2.4.13=np113py27_1 14 | - openssl=1.0.2k=0 15 | - pip=9.0.1=py27_0 16 | - python=2.7.13=1 17 | - readline=6.2=0 18 | - setuptools=33.1.1=py27_0 19 | - sqlite=3.13.0=1 20 | - tk=8.5.19=1 21 | - wheel=0.29.0=py27_0 22 | - xz=5.2.2=0 23 | - zlib=1.2.11=0 24 | - mkl=2017.0.1=0 25 | - numpy=1.13.0=py27_0 26 | - pip: 27 | - pygame==1.9.3 28 | - pyserial==3.3 29 | 30 | -------------------------------------------------------------------------------- /_deprecated/conda-win32.yml: -------------------------------------------------------------------------------- 1 | name: osgar 2 | channels: 3 | - conda-forge 4 | - defaults 5 | dependencies: 6 | - certifi=2017.4.17=py27_0 7 | - jpeg=9b=vc9_0 8 | - libpng=1.6.28=vc9_0 9 | - libtiff=4.0.6=vc9_7 10 | - opencv=2.4.13=np113py27_1 11 | - pip=9.0.1=py27_0 12 | - python=2.7.13=1 13 | - setuptools=33.1.1=py27_0 14 | - vc=9=0 15 | - wheel=0.29.0=py27_0 16 | - wincertstore=0.2=py27_0 17 | - zlib=1.2.11=vc9_0 18 | - mkl=2017.0.1=0 19 | - numpy=1.13.0=py27_0 20 | - vs2008_runtime=9.00.30729.5054=0 21 | - pip: 22 | - pygame==1.9.3 23 | - pyserial==3.3 24 | -------------------------------------------------------------------------------- /_deprecated/config/fill-pattern-15x5.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "johndeere": { 4 | "TURN_ANGLE_OFFSET": 0.05585053606381855 5 | }, 6 | "localization": { 7 | "pose": [4.0, 0.0, 0.0], 8 | "cones": [[0.0, 0.0], [15.0, 0.0], [15.0, 5.0], [0.0, 5.0]] 9 | }, 10 | "navpat": { 11 | "pattern": "fill", 12 | "step": 1.0 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /_deprecated/config/mapit.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "johndeere": { 4 | "TURN_ANGLE_OFFSET": 0.05585053606381855 5 | }, 6 | "localization": { 7 | "pose": [0.5, 0.0, 0.0], 8 | "cones": [] 9 | }, 10 | "navpat": { 11 | "pattern": "mapping", 12 | "step": 1.0 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /_deprecated/config/navpat-default.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "johndeere": { 4 | "TURN_ANGLE_OFFSET": 0.026179938779914945 5 | }, 6 | "localization": { 7 | "pose": [0.0, 2.5, 0.0], 8 | "cones": [[0.0, 0.0], [15.0, 0.0], [15.0, 5.0], [0.0, 5.0]] 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /_deprecated/config/playground15x5.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "johndeere": { 4 | "TURN_ANGLE_OFFSET": 0.05585053606381855 5 | }, 6 | "localization": { 7 | "pose": [-1.3, 2.5, 0.0], 8 | "cones": [[0.0, 0.0], [15.0, 0.0], [15.0, 5.0], [0.0, 5.0]] 9 | } 10 | } 11 | 12 | -------------------------------------------------------------------------------- /_deprecated/helloworld.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | """ 3 | Hello World - minimalistic example 4 | usage: 5 | ./helloworld.py [-h] {run,replay} ... 6 | 7 | positional arguments: 8 | {run,replay} sub-command help 9 | run run on real HW 10 | replay replay from logfile 11 | 12 | optional arguments: 13 | -h, --help show this help message and exit 14 | """ 15 | 16 | from launcher import parse_and_launch 17 | from driver import go_straight 18 | 19 | with parse_and_launch() as (robot, __, __, __): 20 | go_straight(robot, distance=1.0, speed=0.3) 21 | 22 | # vim: expandtab sw=4 ts=4 23 | 24 | -------------------------------------------------------------------------------- /_deprecated/lib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotika/osgar/ab10ba4004329dcc0ea1ffc68ac2334bb1995c38/_deprecated/lib/__init__.py -------------------------------------------------------------------------------- /_deprecated/lib/config.py: -------------------------------------------------------------------------------- 1 | """ 2 | Osgar Config Class 3 | """ 4 | # 5 | # DEPRECATED - current version moved to 6 | # osgar.lib.config 7 | # 8 | import json 9 | 10 | 11 | class Config(object): 12 | 13 | OLD_SUPPORTED_VERSION = 1 14 | ROBOT_CONTAINER_VER = 2 15 | 16 | SUPPORTED_VERSIONS = [OLD_SUPPORTED_VERSION] 17 | 18 | 19 | @classmethod 20 | def load(cls, filename): 21 | return cls.loads(open(filename).read()) 22 | 23 | @classmethod 24 | def loads(cls, text_data): 25 | cls.data = json.loads(text_data) 26 | assert 'version' in cls.data, cls.data 27 | assert cls.data['version'] in cls.SUPPORTED_VERSIONS, cls.data['version'] 28 | cls.version = cls.data['version'] 29 | 30 | return cls 31 | 32 | def __init__(self): 33 | self.data = {} 34 | 35 | # vim: expandtab sw=4 ts=4 36 | -------------------------------------------------------------------------------- /_deprecated/lib/processor.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | """ 3 | Parallel processor/worker/filter for collected sensor data 4 | """ 5 | from multiprocessing import Pool 6 | 7 | 8 | class Processor: 9 | def __init__(self, process_fn): 10 | self.pool = Pool(processes=1) 11 | self.process_fn = process_fn 12 | self.processing = None 13 | 14 | def get_result(self): 15 | if self.processing is None or not self.processing.ready(): 16 | return None 17 | ret = self.processing.get() 18 | self.processing = None 19 | return ret 20 | 21 | def start(self): 22 | pass # only legacy function 23 | 24 | def requestStop(self): 25 | self.pool.close() 26 | 27 | def push_back(self, data): 28 | print("Processor", data) 29 | if self.processing is None: 30 | self.processing = self.pool.apply_async(self.process_fn, (data,)) 31 | else: 32 | print("Skipped", data) 33 | 34 | # vim: expandtab sw=4 ts=4 35 | 36 | -------------------------------------------------------------------------------- /_deprecated/lib/test_config.py: -------------------------------------------------------------------------------- 1 | import os 2 | import unittest 3 | from .config import * 4 | 5 | 6 | def test_data(filename): 7 | return os.path.join(os.path.dirname(__file__), 'test_data', filename) 8 | 9 | 10 | class ConfigTest(unittest.TestCase): 11 | 12 | def test_load(self): 13 | conf = Config.load(test_data('playground12x5.json')) 14 | self.assertEqual(conf.version, 1) 15 | self.assertEqual(len(conf.data['localization']['cones']), 4) 16 | 17 | def test_empty_config(self): 18 | conf = Config() 19 | self.assertIsNone(conf.data.get('localization')) 20 | 21 | if __name__ == "__main__": 22 | unittest.main() 23 | 24 | # vim: expandtab sw=4 ts=4 25 | 26 | -------------------------------------------------------------------------------- /_deprecated/lib/test_data/playground12x5.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "localization": { 4 | "pose": [0.0, 2.5, 0.0], 5 | "cones": [[0.0, 0.0], [12.0, 0.0], [12.0, 5.0], [0.0, 5.0]] 6 | } 7 | } 8 | 9 | -------------------------------------------------------------------------------- /_deprecated/lib/test_localization.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from .localization import SimpleOdometry 3 | 4 | class LocalizationTest(unittest.TestCase): 5 | 6 | def test_from_dict(self): 7 | loc = SimpleOdometry.from_dict({"pose":[1, 2, 3]}) 8 | self.assertEqual(loc.pose(), (1, 2, 3)) 9 | self.assertEqual(loc.global_map, []) 10 | 11 | loc = SimpleOdometry.from_dict({"cones":[[2, 3]]}) 12 | self.assertEqual(loc.pose(), (0, 0, 0)) 13 | self.assertEqual(loc.global_map, [[2, 3]]) 14 | 15 | 16 | if __name__ == "__main__": 17 | unittest.main() 18 | 19 | # vim: expandtab sw=4 ts=4 20 | 21 | -------------------------------------------------------------------------------- /_deprecated/orchard.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | """ 3 | Analysis of Velodyne VLP-16 data - orchard navigation 4 | usage: 5 | ./orchard.py 6 | """ 7 | import sys 8 | import math 9 | from apyros.metalog import MetaLog 10 | from velodyne import Velodyne 11 | 12 | def analyse_alley(raw_data): 13 | s = '' 14 | for i in list(range(270, 360, 5)) + list(range(0, 90, 5)): 15 | dist = raw_data[i:i+5][:,1::2] # use only part related +/- 7 deg 16 | mask = dist > 0 17 | if mask.max(): 18 | d = 0.002*dist[mask].min() 19 | else: 20 | d = 10.0 21 | 22 | ch = ' ' 23 | if d < 2.0: 24 | ch = 'X' 25 | elif d < 4.0: 26 | ch = 'x' 27 | s += ch 28 | return s 29 | 30 | 31 | if __name__ == "__main__": 32 | if len(sys.argv) < 2: 33 | print(__doc__) 34 | sys.exit(2) 35 | assert 'meta_' in sys.argv[1], sys.argv[1] 36 | metalog = MetaLog(filename=sys.argv[1]) 37 | sensor = Velodyne(metalog=metalog) 38 | 39 | 40 | prev = None 41 | while True: 42 | sensor.update() 43 | curr = sensor.scan_index, sensor.safe_dist 44 | if prev != curr: 45 | if sensor.scan_index % 5 == 0 and sensor.scan_index > 0: 46 | # print '-----', sensor.scan_index, '-----' 47 | print(analyse_alley(sensor.dist)) 48 | prev = curr 49 | 50 | # vim: expandtab sw=4 ts=4 51 | 52 | -------------------------------------------------------------------------------- /_deprecated/s60/ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotika/osgar/ab10ba4004329dcc0ea1ffc68ac2334bb1995c38/_deprecated/s60/ball.png -------------------------------------------------------------------------------- /_deprecated/test_column.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from column import * 3 | 4 | class ColumnTest(unittest.TestCase): 5 | 6 | def test_polar2coord(self): 7 | # test55 8 | self.assertEqual(polar2coord( (46, 2.808) ), (1.9506007042488642, -2.019906159350932) ) 9 | self.assertEqual(polar2coord( (196, 1.194) ), (-1.1477464649503528, 0.32911100284549705) ) 10 | 11 | self.assertEqual(polar2coord( (89, 1.762) ), (0.030751140142492875, -1.7617316388655615) ) 12 | self.assertEqual(polar2coord( (269, 1.21) ), (-0.021117411789113007, 1.2098157111392334) ) 13 | 14 | def test_col_dist(self): 15 | self.assertAlmostEqual(col_dist( (89, 1.762), (269, 1.21) ), 2.972) 16 | self.assertAlmostEqual(col_dist( (46, 2.808), (196, 1.194) ), 3.888, 3) # hmmm, probably bug?? 17 | 18 | def test_analyse_pose(self): 19 | p = analyse_pose(prev_pose=None, new_data=[(89, 1.762), (269, 1.21)]) 20 | self.assertEqual(p[0], (2.6194324487249787e-16, 0.2760000000000001, -0.017453292519943098)) 21 | 22 | # select best matching pair 23 | p = analyse_pose(None, [(46, 2.8080000000000003), (169, 5.9500000000000002), (196, 1.194)]) 24 | self.assertEqual(p[0], (0.43115108250453843, 0.8306320134455586, -0.922098513045361)) 25 | 26 | 27 | if __name__ == "__main__": 28 | unittest.main() 29 | 30 | # vim: expandtab sw=4 ts=4 31 | 32 | -------------------------------------------------------------------------------- /_deprecated/test_data/roboorienteering/2015/Kolo0.dat: -------------------------------------------------------------------------------- 1 | S: 50.165704 16.277489 2 | K1: 50.165383 16.277170 42 3 | K2: 50.166031 16.278246 65 4 | K3: 50.165663 16.278085 43 5 | K4: 50.166407 16.278184 93 6 | K5: 50.165462 16.277602 28 7 | C: 50.165786 16.277572 8 | -------------------------------------------------------------------------------- /_deprecated/test_data/roboorienteering/2015/Kolo1.dat: -------------------------------------------------------------------------------- 1 | S: 50.165704 16.277489 2 | K1: 50.165383 16.277170 42 3 | K2: 50.166031 16.278246 65 4 | K3: 50.165663 16.278085 43 5 | K4: 50.166407 16.278184 93 6 | K5: 50.166147 16.278672 98 7 | C: 50.165786 16.277572 8 | -------------------------------------------------------------------------------- /_deprecated/test_data/roboorienteering/2015/Kolo2.dat: -------------------------------------------------------------------------------- 1 | S: 50.166491 16.278013 2 | K1: 50.166147 16.278672 61 3 | K2: 50.166661 16.278495 39 4 | K3: 50.165663 16.278085 92 5 | K4: 50.166407 16.278184 15 6 | K5: 50.165462 16.277602 118 7 | K6: 50.166031 16.278246 54 8 | K7: 50.166393 16.279233 88 9 | C: 50.166417 16.277916 10 | -------------------------------------------------------------------------------- /_deprecated/test_data/roboorienteering/2015/Kolo3.dat: -------------------------------------------------------------------------------- 1 | S: 50.166834 16.278471 2 | K1: 50.166147 16.278672 78 3 | K2: 50.166661 16.278495 19 4 | K3: 50.165663 16.278085 133 5 | K4: 50.166407 16.278184 52 6 | K5: 50.165462 16.277602 165 7 | K6: 50.166031 16.278246 91 8 | K7: 50.166393 16.279233 73 9 | C: 50.166869 16.278554 10 | -------------------------------------------------------------------------------- /_deprecated/test_data/roboorienteering/2016/Kolo2.dat: -------------------------------------------------------------------------------- 1 | S: 50.166491 16.278013 2 | K1: 50.166352 16.278328 27 3 | K2: 50.166589 16.278534 39 4 | K3: 50.166401 16.279228 87 5 | K4: 50.166147 16.278672 61 6 | K5: 50.165663 16.278085 92 7 | K6: 50.165900 16.277964 66 8 | K7: 50.166031 16.278246 54 9 | C: 50.166417 16.277916 10 | -------------------------------------------------------------------------------- /_deprecated/test_data/roboorienteering/2016/Kolo3.dat: -------------------------------------------------------------------------------- 1 | S: 50.165860 16.278386 2 | K1: 50.165417 16.277772 66 3 | K2: 50.165663 16.278085 31 4 | K3: 50.165900 16.277964 30 5 | K4: 50.166352 16.278328 55 6 | K5: 50.166589 16.278534 82 7 | K6: 50.166493 16.278985 82 8 | K7: 50.166401 16.279228 85 9 | C: 50.166147 16.278672 10 | -------------------------------------------------------------------------------- /_deprecated/tools/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotika/osgar/ab10ba4004329dcc0ea1ffc68ac2334bb1995c38/_deprecated/tools/__init__.py -------------------------------------------------------------------------------- /_deprecated/webserver/README.md: -------------------------------------------------------------------------------- 1 | Python Webserver for IQ80 Network - version 0 2 | 3 | Installation (win32) 4 | 5 | 1) Install Python 6 | for example http://python.org/ftp/python/2.7.2/python-2.7.2.msi 7 | 8 | 2) Install PySerial 9 | http://sourceforge.net/projects/pyserial/files/pyserial/2.5/pyserial-2.5.win32.exe/download?source=files 10 | 11 | 3) Download jquery.js 12 | http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js 13 | (this is for installation without internet connection - otherwise you can modify lights.html for direct download) 14 | 15 | 4) Test dummy webserver: 16 | files: 17 | web2.py - web server 18 | controller.py - connection to serial line 19 | lights.html - main webpage 20 | jquery.js - java script for main page 21 | 22 | Run: web2.py dummy 23 | - it starts webserver without connection to serial port 24 | - in Mozilla set URL to http://localhost/ and you should see four rooms 25 | 26 | 5) Test webserver with COM: 27 | Run: web2.py COM6 (for example if COM6 is the connected COM port) 28 | On 9600 it sends readable ASCII commands 29 | For status info is used simple "procotol" 'a'..'z' lights off, 'A'..'Z' lights on 30 | 31 | -------------------------------------------------------------------------------- /_deprecated/webserver/controller.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import serial 3 | from threading import Thread 4 | 5 | class DummyController: 6 | def __init__( self ): 7 | self.status = {} 8 | def send( self, nodeId, cmd ): 9 | print("SEND", nodeId, cmd) 10 | self.status[ nodeId ] = cmd 11 | 12 | def query( self, nodeId ): 13 | return self.status.get( nodeId, "unknown" ) 14 | 15 | class Controller( Thread ): 16 | def __init__( self, comname ): 17 | self.com = serial.Serial( comname, 9600, timeout=1.0 ) 18 | self.status = {} 19 | Thread.__init__(self) 20 | self.setDaemon(True) 21 | self.start() 22 | 23 | def send( self, nodeId, cmd ): 24 | print("SEND", nodeId, cmd) 25 | self.com.write( str( ("SEND", nodeId, cmd) ) + "\r\n" ) 26 | self.status[ nodeId ] = cmd # pre-optimistics, remove if necessary 27 | 28 | def query( self, nodeId ): 29 | return self.status.get( nodeId, "unknown" ) 30 | 31 | def run( self ): 32 | print("THREAD") 33 | while( 1 ): 34 | s = self.com.read(1) 35 | print(s) 36 | if len(s) > 0: 37 | ch = s[0] 38 | if ch >= 'a' and ch <= 'z': 39 | self.status[ ord(ch)-ord('a')+1 ] = "off" 40 | if ch >= 'A' and ch <= 'Z': 41 | self.status[ ord(ch)-ord('A')+1 ] = "on" 42 | 43 | -------------------------------------------------------------------------------- /config/cortexpilot-no-camera.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "driver": "application", 7 | "in": ["emergency_stop", "pose2d"], 8 | "out": ["desired_speed"], 9 | "init": { 10 | "max_speed": 0.5 11 | } 12 | }, 13 | "cortexpilot": { 14 | "driver": "osgar.drivers.cortexpilot:Cortexpilot", 15 | "in": ["raw", "desired_speed"], 16 | "out": ["raw", "encoders", "emergency_stop", "pose2d", "scan"], 17 | "init": {} 18 | }, 19 | "serial": { 20 | "driver": "serial", 21 | "in": ["raw"], 22 | "out": ["raw"], 23 | "init": {"port": "/dev/ttyACM0", "speed": 115200} 24 | } 25 | }, 26 | "links": [["app.desired_speed", "cortexpilot.desired_speed"], 27 | ["cortexpilot.pose2d", "app.pose2d"], 28 | ["cortexpilot.emergency_stop", "app.emergency_stop"], 29 | ["serial.raw", "cortexpilot.raw"], 30 | ["cortexpilot.raw", "serial.raw"], 31 | ["cortexpilot.scan", "app.scan"]] 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /config/cortexpilot-only.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "cortexpilot": { 6 | "driver": "osgar.drivers.cortexpilot:Cortexpilot", 7 | "in": ["raw", "desired_speed"], 8 | "out": ["raw", "encoders", "emergency_stop", "pose2d", "scan", "orientation", "rotation", "voltage"], 9 | "init": {} 10 | }, 11 | "serial": { 12 | "driver": "serial", 13 | "in": ["raw"], 14 | "out": ["raw"], 15 | "init": {"port": "/dev/ttyACM0", "speed": 115200} 16 | } 17 | }, 18 | "links": [ 19 | ["serial.raw", "cortexpilot.raw"], 20 | ["cortexpilot.raw", "serial.raw"] 21 | ] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /config/deedee-demo.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "timer": { 6 | "driver": "timer", 7 | "in": [], 8 | "out": ["tick"], 9 | "init": { 10 | "sleep": 0.05 11 | } 12 | }, 13 | "demo": { 14 | "driver": "osgar.drivers.deedee:Demo", 15 | "in": ["tick", "pose2d"], 16 | "out": ["desired_speed"] 17 | }, 18 | "deedee": { 19 | "driver": "osgar.drivers.deedee:Deedee", 20 | "in": ["desired_speed", "info", "tick"], 21 | "out": ["cmd", "pose2d", "emergency_stop", "stdout"], 22 | "init": {} 23 | }, 24 | "slip": { 25 | "driver": "osgar.drivers.deedee:Slip", 26 | "in": ["packet", "raw"], 27 | "out": ["packet", "raw"], 28 | "init": {} 29 | }, 30 | "serial": { 31 | "driver": "serial", 32 | "in": ["raw"], 33 | "out": ["raw"], 34 | "init": {"port": "/dev/ttyUSB0", 35 | "speed": 115200, 36 | "reset": 1} 37 | } 38 | }, 39 | "links": [["timer.tick", "deedee.tick"], 40 | ["demo.desired_speed", "deedee.desired_speed"], 41 | ["deedee.cmd", "slip.packet"], 42 | ["deedee.pose2d", "demo.pose2d"], 43 | ["slip.packet", "deedee.info"], 44 | ["slip.raw", "serial.raw"], 45 | ["serial.raw", "slip.raw"]] 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /config/dual-qorvo.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "timer": { 6 | "driver": "timer", 7 | "init": { 8 | "sleep": 1.0 9 | } 10 | }, 11 | "qorvo": { 12 | "driver": "osgar.drivers.qorvo:Qorvo", 13 | "in": ["raw"], 14 | "out": ["range", "raw"], 15 | "init": { 16 | } 17 | }, 18 | "qserial": { 19 | "driver": "serial", 20 | "in": ["raw"], 21 | "out": ["raw"], 22 | "init": { 23 | "port": "/dev/ttyACM0", 24 | "speed": 115200 25 | } 26 | }, 27 | "qorvo2": { 28 | "driver": "osgar.drivers.qorvo:Qorvo", 29 | "in": ["raw"], 30 | "out": ["range", "raw"], 31 | "init": { 32 | } 33 | }, 34 | "qserial2": { 35 | "driver": "serial", 36 | "in": ["raw"], 37 | "out": ["raw"], 38 | "init": { 39 | "port": "/dev/ttyACM1", 40 | "speed": 115200 41 | } 42 | } 43 | }, 44 | "links": [ 45 | ["timer.tick", "qorvo.timer"], 46 | ["qorvo.raw", "qserial.raw"], 47 | ["qserial.raw", "qorvo.raw"], 48 | 49 | ["timer.tick", "qorvo2.timer"], 50 | ["qorvo2.raw", "qserial2.raw"], 51 | ["qserial2.raw", "qorvo2.raw"] 52 | ] 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /config/explore-left-wall.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "init": { 7 | "right_wall": false 8 | } 9 | } 10 | } 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /config/explore-right-wall.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "init": { 7 | "right_wall": true 8 | } 9 | } 10 | } 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /config/gps-mpfc-linux.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "gps": { 6 | "driver": "gps", 7 | "in": ["raw"], 8 | "out": ["position"], 9 | "init": {} 10 | }, 11 | "gps_serial": { 12 | "driver": "serial", 13 | "in": [], 14 | "out": ["raw"], 15 | "init": {"port": "/dev/ttyUSB0", "speed": 4800} 16 | } 17 | }, 18 | "links": [["gps_serial.raw", "gps.raw"]] 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /config/gps-pozyx.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "gps": { 6 | "driver": "gps", 7 | "in": ["raw"], 8 | "out": ["position"], 9 | "init": {} 10 | }, 11 | "gps_serial": { 12 | "driver": "serial", 13 | "in": [], 14 | "out": ["raw"], 15 | "init": {"port": "/dev/ttyUSB0", "speed": 4800} 16 | }, 17 | "pozyx": { 18 | "driver": "pozyx", 19 | "in": [], 20 | "out": ["range"], 21 | "init": { 22 | "port": "/dev/ttyACM0", 23 | "devices": ["0x0D67", "0x0D7F", "0x0D53", "0x6826"] 24 | } 25 | } 26 | }, 27 | "links": [["gps_serial.raw", "gps.raw"]] 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /config/kloubak-slot.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "driver": "application", 7 | "in": ["emergency_stop", "pose2d"], 8 | "out": ["desired_speed"], 9 | "init": { 10 | "max_speed": 0.5 11 | } 12 | }, 13 | "kloubak": { 14 | "driver": "kloubak", 15 | "in": ["slot_can", "slot_desired_speed"], 16 | "out": ["can", "encoders", "emergency_stop", "pose2d"], 17 | "init": {} 18 | }, 19 | "can": { 20 | "driver": "can", 21 | "in": ["slot_raw", "slot_can"], 22 | "out": ["can", "raw"], 23 | "init": {"speed": "500k", "canopen":false} 24 | }, 25 | "serial": { 26 | "driver": "serial", 27 | "in": ["slot_raw"], 28 | "out": ["raw"], 29 | "init": {"port": "/dev/ttyS0", "speed": 115200, 30 | "rtscts":true, "reset":true, 31 | "timeout": 0.001} 32 | } 33 | }, 34 | "links": [["serial.raw", "can.slot_raw"], 35 | ["can.raw", "serial.slot_raw"], 36 | ["kloubak.can", "can.slot_can"], 37 | ["can.can", "kloubak.slot_can"], 38 | ["app.desired_speed", "kloubak.slot_desired_speed"], 39 | ["kloubak.pose2d", "app.pose2d"] 40 | ] 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /config/maria-realsense.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "driver": "application", 7 | "in": ["emergency_stop", "pose2d"], 8 | "out": ["desired_speed"], 9 | "init": { 10 | "max_speed": 0.5 11 | } 12 | }, 13 | "maria": { 14 | "driver": "tankmaria", 15 | "in": ["desired_speed", "raw", "pwm"], 16 | "out": ["emergency_stop", "pose2d", "raw", "encoders"], 17 | "init": {} 18 | }, 19 | "timer": { 20 | "driver": "timer", 21 | "in": [], 22 | "out": ["tick"], 23 | "init": { 24 | "sleep": 0.1 25 | } 26 | }, 27 | "serial": { 28 | "driver": "serial", 29 | "in": ["raw"], 30 | "out": ["raw"], 31 | "init": {"port": "/dev/arduino-motor", "speed": 115200} 32 | }, 33 | "rs": { 34 | "driver": "realsense", 35 | "in": ["trigger"], 36 | "out": ["pose2d"], 37 | "init": {} 38 | } 39 | }, 40 | "links": [["app.desired_speed", "maria.desired_speed"], 41 | ["maria.emergency_stop", "app.emergency_stop"], 42 | ["maria.pose2d", "app.pose2d"], 43 | ["serial.raw", "maria.raw"], 44 | ["maria.raw", "serial.raw"], 45 | ["timer.tick", "rs.trigger"]] 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /config/maria.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "driver": "application", 7 | "in": ["emergency_stop", "pose2d"], 8 | "out": ["desired_speed"], 9 | "init": { 10 | "max_speed": 0.75 11 | } 12 | }, 13 | "maria": { 14 | "driver": "maria", 15 | "in": ["desired_speed", "raw"], 16 | "out": ["emergency_stop", "pose2d", "raw", "encoders"], 17 | "init": {} 18 | }, 19 | "serial": { 20 | "driver": "serial", 21 | "in": ["raw"], 22 | "out": ["raw"], 23 | "init": {"port": "/dev/arduino-motor", "speed": 115200} 24 | } 25 | }, 26 | "links": [["app.desired_speed", "maria.desired_speed"], 27 | ["maria.emergency_stop", "app.emergency_stop"], 28 | ["maria.pose2d", "app.pose2d"], 29 | ["serial.raw", "maria.raw"], 30 | ["maria.raw", "serial.raw"]] 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /config/matty-go.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "driver": "osgar.go:Go", 7 | "in": ["emergency_stop", "pose2d"], 8 | "out": ["desired_speed"], 9 | "init": { 10 | "max_speed": 0.2, 11 | "dist": 1.0, 12 | "timeout": 10 13 | } 14 | }, 15 | "platform": { 16 | "driver": "osgar.platforms.matty:Matty", 17 | "in": ["esp_data"], 18 | "out": ["esp_data"], 19 | "init": {} 20 | }, 21 | "gps": { 22 | "driver": "gps", 23 | "in": ["raw"], 24 | "out": ["nmea_data"], 25 | "init": {} 26 | }, 27 | "timer": { 28 | "driver": "timer", 29 | "in": [], 30 | "out": ["tick"], 31 | "init": { 32 | "sleep": 0.1 33 | } 34 | }, 35 | "serial": { 36 | "driver": "serial", 37 | "in": ["raw"], 38 | "out": ["raw"], 39 | "init": {"port": "/dev/ttyUSB0", "speed": 115200} 40 | } 41 | }, 42 | "links": [ 43 | ["app.desired_steering", "platform.desired_steering"], 44 | ["platform.pose2d", "app.pose2d"], 45 | ["serial.raw", "platform.esp_data"], 46 | ["platform.esp_data", "serial.raw"], 47 | ["platform.gps_serial", "gps.raw"], 48 | ["timer.tick", "platform.tick"] 49 | ] 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /config/myrobot-lora.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "driver": "application", 7 | "in": ["emergency_stop", "pose2d"], 8 | "out": ["desired_speed"], 9 | "init": { 10 | "max_speed": 0.5 11 | } 12 | }, 13 | "myrobot": { 14 | "driver": "myrobot:MyRobot", 15 | "in": ["desired_speed"], 16 | "out": ["emergency_stop", "pose2d"], 17 | "init": {} 18 | }, 19 | "timer": { 20 | "driver": "myrobot:MyTimer", 21 | "in": [], 22 | "out": ["tick"], 23 | "init": { 24 | "sleep": 0.1 25 | } 26 | }, 27 | "lora": { 28 | "driver": "lora", 29 | "in": ["raw", "pose2d"], 30 | "out": ["raw"], 31 | "init": {} 32 | }, 33 | "lora_serial": { 34 | "driver": "serial", 35 | "in": ["raw"], 36 | "out": ["raw"], 37 | "init": {"port": "/dev/ttyUSB0", "speed": 115200} 38 | } 39 | }, 40 | "links": [["app.desired_speed", "myrobot.desired_speed"], 41 | ["myrobot.emergency_stop", "app.emergency_stop"], 42 | ["myrobot.pose2d", "app.pose2d"], 43 | ["timer.tick", "myrobot.tick"], 44 | ["lora_serial.raw", "lora.raw"], 45 | ["lora.raw", "lora_serial.raw"], 46 | ["myrobot.pose2d", "lora.pose2d"]] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /config/pcan-kloubak.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "driver": "application", 7 | "in": ["emergency_stop", "pose2d"], 8 | "out": ["desired_speed"], 9 | "init": { 10 | "max_speed": 0.5 11 | } 12 | }, 13 | "kloubak": { 14 | "driver": "kloubak", 15 | "in": ["can", "desired_speed"], 16 | "out": ["can", "encoders", "emergency_stop", "pose2d"], 17 | "init": {} 18 | }, 19 | "can": { 20 | "driver": "pcan", 21 | "in": ["can"], 22 | "out": ["can"], 23 | "init": {} 24 | } 25 | }, 26 | "links": [["kloubak.can", "can.can"], 27 | ["can.can", "kloubak.can"], 28 | ["app.desired_speed", "kloubak.desired_speed"], 29 | ["kloubak.pose2d", "app.pose2d"] 30 | ] 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /config/pozyx-io.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "pozyx": { 6 | "driver": "pozyx", 7 | "in": [], 8 | "out": ["range", "gpio"], 9 | "init": { 10 | "port": "/dev/ttyACM0", 11 | "devices": ["0xD67", "0xD53","0x6827"], 12 | "gpio": ["0x6827"] 13 | } 14 | } 15 | }, 16 | "links": [] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /config/ro2018-czu-waypoints.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "init": { 7 | "maxspeed": 10, 8 | "waypoints": [[50.1283538, 14.3752654], 9 | [50.1281866, 14.3736720]] 10 | } 11 | } 12 | } 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /config/ro2018-simulation.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "driver": "application", 7 | "in": ["position", "orientation", "status"], 8 | "out": ["move"], 9 | "init": {} 10 | }, 11 | "spider": { 12 | "driver": "simulator", 13 | "in": ["move"], 14 | "out": ["position", "orientation", "status"], 15 | "init": { 16 | "position":[51748232, 180462052], 17 | "duration": 200.0 18 | } 19 | } 20 | }, 21 | "links": [["spider.position", "app.position"], 22 | ["spider.orientation", "app.orientation"], 23 | ["spider.status", "app.status"], 24 | ["app.move", "spider.move"]] 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /config/ro2019-waypoints.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "init": { 7 | "waypoints": [[49.949526, 12.697371], 8 | [49.950105, 12.696098], 9 | [49.950455, 12.696915], 10 | [49.949334, 12.698294], 11 | [49.948960, 12.698260], 12 | [49.948932, 12.698031]] 13 | } 14 | } 15 | } 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /config/skiddy-subt-serialloop.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "serial": { 6 | "driver": "subt.serialloop:SerialLoop", 7 | "in": ["raw"], 8 | "out": ["raw"], 9 | "init": {"port": "/dev/ttyACM0", "speed": 115200, "timeout": 0.02} 10 | }, 11 | "fromapp": { 12 | "driver": "osgar.drivers.pull:Pull", 13 | "out": ["raw"], 14 | "init": { 15 | "endpoint": "tcp://127.0.0.1:5590", 16 | "bind": true, 17 | "outputs": ["raw"] 18 | } 19 | }, 20 | "toapp": { 21 | "driver": "osgar.drivers.push:Push", 22 | "init": { 23 | "endpoint": "tcp://127.0.0.1:5591", 24 | "bind": true 25 | } 26 | } 27 | }, 28 | "links": [["fromapp.raw", "serial.raw"], 29 | ["serial.raw", "toapp.raw"]] 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /config/spider-camera.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "driver": "application", 7 | "in": [], 8 | "out": ["desired_speed"], 9 | "init": { 10 | "max_speed": 0.5 11 | } 12 | }, 13 | "spider": { 14 | "driver": "spider", 15 | "in": ["can", "move"], 16 | "out": ["can"], 17 | "init": {} 18 | }, 19 | "can": { 20 | "driver": "can", 21 | "in": ["raw", "can"], 22 | "out": ["can", "raw"], 23 | "init": {} 24 | }, 25 | "serial": { 26 | "driver": "serial", 27 | "in": ["raw"], 28 | "out": ["raw"], 29 | "init": {"port": "/dev/ttyS0", "speed": 115200, 30 | "rtscts":true, "reset":true} 31 | }, 32 | "camera": { 33 | "driver": "http", 34 | "in": [], 35 | "out": ["raw"], 36 | "init": { 37 | "url": "http://192.168.1.36/img.jpg", 38 | "sleep": 0.2, 39 | "timeout": 1.0 40 | } 41 | } 42 | }, 43 | "links": [["app.desired_speed", "spider.move"], 44 | ["spider.status", "app.status"], 45 | ["spider.pose2d", "app.pose2d"], 46 | ["spider.can", "can.can"], 47 | ["can.can", "spider.can"], 48 | ["serial.raw", "can.raw"], 49 | ["can.raw", "serial.raw"]] 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /config/spider.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "driver": "application", 7 | "in": [], 8 | "out": ["desired_speed"], 9 | "init": { 10 | "max_speed": 0.5 11 | } 12 | }, 13 | "spider": { 14 | "driver": "spider", 15 | "in": ["can", "move"], 16 | "out": ["can"], 17 | "init": {} 18 | }, 19 | "can": { 20 | "driver": "can", 21 | "in": ["raw", "can"], 22 | "out": ["can", "raw"], 23 | "init": {} 24 | }, 25 | "serial": { 26 | "driver": "serial", 27 | "in": ["raw"], 28 | "out": ["raw"], 29 | "init": {"port": "/dev/ttyS0", "speed": 115200, 30 | "rtscts":true, "reset":true} 31 | } 32 | }, 33 | "links": [["app.desired_speed", "spider.move"], 34 | ["spider.pose2d", "app.pose2d"], 35 | ["spider.can", "can.can"], 36 | ["can.can", "spider.can"], 37 | ["serial.raw", "can.raw"], 38 | ["can.raw", "serial.raw"]] 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /config/subt-e-stop-windows-A24.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "estop": { 6 | "driver": "subt.estop:EStop", 7 | "in": ["raw"], 8 | "out": ["raw", "emergency_stop"], 9 | "init": { 10 | "master": true 11 | } 12 | }, 13 | "estop_serial": { 14 | "driver": "serial", 15 | "in": ["raw"], 16 | "out": ["raw"], 17 | "init": {"port": "COM31", "speed": 9600} 18 | } 19 | }, 20 | "links": [["estop_serial.raw", "estop.raw"], 21 | ["estop.raw", "estop_serial.raw"]] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /config/subt-e-stop-windows.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "estop": { 6 | "driver": "subt.estop:EStop", 7 | "in": ["raw"], 8 | "out": ["raw", "emergency_stop"], 9 | "init": {} 10 | }, 11 | "estop_serial": { 12 | "driver": "serial", 13 | "in": ["raw"], 14 | "out": ["raw"], 15 | "init": {"port": "COM29", "speed": 9600} 16 | } 17 | }, 18 | "links": [["estop_serial.raw", "estop.raw"], 19 | ["estop.raw", "estop_serial.raw"]] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /config/test-canserial.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "spider_can": { 6 | "driver": "can", 7 | "in": ["raw", "can"], 8 | "out": ["can", "raw"], 9 | "init": {} 10 | }, 11 | "spider_serial": { 12 | "driver": "serial", 13 | "in": ["raw"], 14 | "out": ["raw"], 15 | "init": {"port": "/dev/ttyS0", "speed": 115200, 16 | "rtscts":true, "reset":true} 17 | } 18 | }, 19 | "links": [["spider_serial.raw", "spider_can.raw"], 20 | ["spider_can.raw", "spider_serial.raw"]] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /config/test-dual-timer.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "timer1": { 6 | "driver": "timer", 7 | "in": [], 8 | "out": ["tick"], 9 | "init": { 10 | "sleep": 0.1 11 | } 12 | }, 13 | "timer2": { 14 | "driver": "timer", 15 | "in": [], 16 | "out": ["tick"], 17 | "init": { 18 | "sleep": 0.2 19 | } 20 | } 21 | }, 22 | "links": [] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /config/test-estop.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "estop": { 6 | "driver": "subt.estop:EStop", 7 | "in": ["raw"], 8 | "out": ["raw", "emergency_stop"], 9 | "init": {} 10 | }, 11 | "estop_serial": { 12 | "driver": "serial", 13 | "in": ["raw"], 14 | "out": ["raw"], 15 | "init": {"port": "/dev/estop", "speed": 9600} 16 | } 17 | }, 18 | "links": [["estop_serial.raw", "estop.raw"], 19 | ["estop.raw", "estop_serial.raw"]] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /config/test-eth-gps-bridge.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "gps_tcp": { 6 | "driver": "tcp", 7 | "in": ["raw"], 8 | "out": ["raw"], 9 | "init": { 10 | "host": "192.168.1.10", 11 | "port": 10001, 12 | "bufsize": 2000 13 | } 14 | }, 15 | "gps": { 16 | "driver": "gps", 17 | "init": {} 18 | }, 19 | "rtk_filter": { 20 | "driver": "rtk_filter", 21 | "in": ["nmea"], 22 | "out": ["filtered"], 23 | "init": { 24 | } 25 | }, 26 | "rtk_modem": { 27 | "driver": "tcp", 28 | "in": ["raw"], 29 | "out": ["raw"], 30 | "init": { 31 | "host": "192.168.1.11", 32 | "port": 10001, 33 | "bufsize": 2000 34 | } 35 | } 36 | }, 37 | "links": [["gps_tcp.raw", "gps.raw"], 38 | ["gps_tcp.raw", "rtk_filter.nmea"], 39 | ["rtk_filter.filtered", "rtk_modem.raw"], 40 | ["rtk_modem.raw", "gps_tcp.raw"]] 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /config/test-eth-gps.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "gps": { 6 | "driver": "tcp", 7 | "in": ["raw"], 8 | "out": ["raw"], 9 | "init": { 10 | "host": "192.168.2.10", 11 | "port": 10001, 12 | "bufsize": 2000 13 | } 14 | } 15 | }, 16 | "links": [] 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /config/test-eth-imu.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "imu": { 6 | "driver": "imu", 7 | "in": ["raw"], 8 | "out": ["orientation", "rotation", "data"], 9 | "init": {} 10 | }, 11 | "imu_tcp": { 12 | "driver": "tcp", 13 | "in": ["raw"], 14 | "out": ["raw"], 15 | "init": { 16 | "host": "192.168.1.12", 17 | "port": 10002, 18 | "bufsize": 2000 19 | } 20 | } 21 | }, 22 | "links": [["imu_tcp.raw", "imu.raw"]] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /config/test-fr07.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "platform": { 6 | "driver": "osgar.platforms.yuhesen:FR07", 7 | "in": ["can"], 8 | "out": ["can"], 9 | "init": {} 10 | }, 11 | "can": { 12 | "driver": "pcan", 13 | "in": ["can"], 14 | "out": ["can"], 15 | "init": {} 16 | } 17 | }, 18 | "links": [ 19 | ["can.can", "platform.can"], 20 | ["platform.can", "can.can"] 21 | ] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /config/test-fusion.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "replay": { 6 | "driver": "replay", 7 | "in": [], 8 | "out": ["pose2d", "scan", "jpeg", "rotation"], 9 | "init": { 10 | "filename": "d:\\md\\osgar\\logs\\subt\\eduro\\190305\\wall-190305_203603.log", 11 | "pins": { 12 | "eduro.pose2d": "pose2d", 13 | "lidar.scan": "scan", 14 | "imu.rot": "rotation", 15 | "camera.raw": "jpeg" 16 | } 17 | } 18 | }, 19 | "fusion": { 20 | "driver": "osgar.drivers.fusion:FusionPose2d", 21 | "in": ["pose2d", "rotation"], 22 | "out": ["pose2d"], 23 | "init": {} 24 | } 25 | }, 26 | "links": [["replay.pose2d", "fusion.pose2d"], 27 | ["replay.rotation", "fusion.rotation"]] 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /config/test-gas-detector.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "gas_detector": { 6 | "driver": "osgar.drivers.gas_detector:MeasureCO2", 7 | "in": ["raw"], 8 | "out": ["raw", "co2"], 9 | "init": { 10 | "sleep": 0.5 11 | } 12 | }, 13 | "serial": { 14 | "driver": "serial", 15 | "in": ["raw"], 16 | "out": ["raw"], 17 | "init": {"port": "COM4", "speed": 115200} 18 | } 19 | }, 20 | "links": [ 21 | ["serial.raw", "gas_detector.raw"], 22 | ["gas_detector.raw", "serial.raw"] 23 | ] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /config/test-gps-imu.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "gps": { 6 | "driver": "gps", 7 | "in": ["raw"], 8 | "out": ["position", "rel_position"], 9 | "init": {} 10 | }, 11 | "gps_serial": { 12 | "driver": "serial", 13 | "in": [], 14 | "out": ["raw"], 15 | "init": {"port": "/dev/ttyACM0", "speed": 115200} 16 | }, 17 | "imu": { 18 | "driver": "imu", 19 | "in": ["raw"], 20 | "out": ["orientation"], 21 | "init": {} 22 | }, 23 | "imu_serial": { 24 | "driver": "serial", 25 | "in": [], 26 | "out": ["raw"], 27 | "init": {"port": "/dev/ttyUSB0", "speed": 115200} 28 | } 29 | }, 30 | "links": [["gps_serial.raw", "gps.raw"], ["imu_serial.raw", "imu.raw"]] 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /config/test-ip-camera.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "camera": { 6 | "driver": "http", 7 | "in": [], 8 | "out": ["raw"], 9 | "init": { 10 | "url": "http://192.168.0.99/img.jpg", 11 | "sleep": 0.5, 12 | "timeout": 1.0 13 | } 14 | } 15 | }, 16 | "links": [] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /config/test-jetson_artf_node.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "camera": { 6 | "driver": "osgar.drivers.opencv:LogOpenCVCamera", 7 | "in": [], 8 | "out": ["raw"], 9 | "init": { 10 | "port": 0, 11 | "sleep": 1.0 12 | } 13 | }, 14 | "detector":{ 15 | "driver": "subt.jetson_artf_node:ArtifactDetectorJetson", 16 | "in": ["image"], 17 | "out": ["localized_artf", "dropped", "debug_image", "debug_result"], 18 | "init": {} 19 | 20 | } 21 | }, 22 | "links": [["camera.raw", "detector.image"]] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /config/test-lidar-tim571.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "lidar": { 6 | "driver": "lidar", 7 | "in": ["raw"], 8 | "out": ["raw", "scan"], 9 | "init": {} 10 | }, 11 | "lidar_tcp": { 12 | "driver": "tcp", 13 | "in": ["raw"], 14 | "out": ["raw"], 15 | "init": {"host": "192.168.2.71", "port": 2111, "timeout": 3.0} 16 | } 17 | }, 18 | "links": [["lidar_tcp.raw", "lidar.raw"], 19 | ["lidar.raw", "lidar_tcp.raw"] 20 | ] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /config/test-lora-windows.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "lora": { 6 | "driver": "lora", 7 | "in": ["raw"], 8 | "out": ["raw", "cmd"], 9 | "init": { 10 | "sleep": 20, 11 | "verbose": true 12 | } 13 | }, 14 | "lora_serial": { 15 | "driver": "serial", 16 | "in": ["raw"], 17 | "out": ["raw"], 18 | "init": {"port": "COM35", "speed": 115200} 19 | } 20 | }, 21 | "links": [["lora_serial.raw", "lora.raw"], 22 | ["lora.raw", "lora_serial.raw"]] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /config/test-lora.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "lora": { 6 | "driver": "lora", 7 | "in": ["raw"], 8 | "out": ["raw", "cmd"], 9 | "init": {} 10 | }, 11 | "lora_serial": { 12 | "driver": "serial", 13 | "in": ["raw"], 14 | "out": ["raw"], 15 | "init": {"port": "/dev/lora", "speed": 115200} 16 | } 17 | }, 18 | "links": [["lora_serial.raw", "lora.raw"], 19 | ["lora.raw", "lora_serial.raw"]] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /config/test-lord-imu-linux.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "imu": { 6 | "driver": "lordimu", 7 | "in": ["raw"], 8 | "out": ["orientation", "rotation"], 9 | "init": {} 10 | }, 11 | "imu_serial": { 12 | "driver": "serial", 13 | "in": [], 14 | "out": ["raw"], 15 | "init": {"port": "/dev/ttyACM0", "speed": 115200} 16 | } 17 | }, 18 | "links": [["imu_serial.raw", "imu.raw"]] 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /config/test-lord-imu.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "imu": { 6 | "driver": "lordimu", 7 | "in": ["raw"], 8 | "out": ["orientation", "rotation"], 9 | "init": {} 10 | }, 11 | "imu_serial": { 12 | "driver": "serial", 13 | "in": [], 14 | "out": ["raw"], 15 | "init": {"port": "COM30", "speed": 115200} 16 | } 17 | }, 18 | "links": [["imu_serial.raw", "imu.raw"]] 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /config/test-matty.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "platform": { 6 | "driver": "osgar.platforms.matty:Matty", 7 | "in": ["esp_data"], 8 | "out": ["esp_data"], 9 | "init": {} 10 | }, 11 | "timer": { 12 | "driver": "timer", 13 | "in": [], 14 | "out": ["tick"], 15 | "init": { 16 | "sleep": 0.1 17 | } 18 | }, 19 | "serial": { 20 | "driver": "serial", 21 | "in": ["raw"], 22 | "out": ["raw"], 23 | "init": {"port": "/dev/ttyUSB0", "speed": 115200} 24 | } 25 | }, 26 | "links": [ 27 | ["serial.raw", "platform.esp_data"], 28 | ["platform.esp_data", "serial.raw"], 29 | ["timer.tick", "platform.tick"] 30 | ] 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /config/test-o3d3xx.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "driver": "osgar.drivers.o3d3xx_camera:O3DCamera", 7 | "init": { 8 | "resolution": [352, 264] 9 | } 10 | } 11 | }, 12 | "links": [] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /config/test-oak-camera-usb.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "oak": { 6 | "driver": "osgar.drivers.oak_camera:OakCamera", 7 | "init": { 8 | "fps": 10, 9 | "is_color": true, 10 | "video_encoder": "h264", 11 | "is_depth": true, 12 | "laser_projector_current": 0, 13 | "flood_light_current": 500, 14 | "is_imu_enabled": true, 15 | "number_imu_records": 10, 16 | "disable_magnetometer_fusion": false, 17 | 18 | "mono_resolution": "THE_400_P", 19 | "color_resolution": "THE_1080_P", 20 | "color_manual_focus": 130, 21 | 22 | "stereo_median_filter": "KERNEL_3x3", 23 | "stereo_mode": "HIGH_ACCURACY", 24 | "stereo_extended_disparity": false, 25 | "stereo_subpixel": false, 26 | "stereo_left_right_check": true 27 | } 28 | } 29 | }, 30 | "links": [] 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /config/test-oak-camera.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "driver": "osgar.drivers.oak_camera:OakCamera", 7 | "init": { 8 | "fps": 10, 9 | "is_color": true, 10 | "is_depth": true, 11 | "laser_projector_current": 1200, 12 | "is_imu_enabled": true, 13 | "number_imu_records": 10, 14 | "disable_magnetometer_fusion": false, 15 | "cam_id": "169.254.1.222", 16 | 17 | "mono_resolution": "THE_400_P", 18 | "color_resolution": "THE_1080_P", 19 | "color_manual_focus": 130, 20 | "color_manual_exposure": null, 21 | 22 | "stereo_median_filter": "KERNEL_3x3", 23 | "stereo_mode": "HIGH_ACCURACY", 24 | "stereo_extended_disparity": false, 25 | "stereo_subpixel": false, 26 | "stereo_left_right_check": true, 27 | "color_depth_alignment": true 28 | } 29 | } 30 | }, 31 | "links": [] 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /config/test-oak-sr-usb.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "oak": { 6 | "driver": "osgar.drivers.oak_camera:OakCamera", 7 | "init": { 8 | "cam_id": "1.1", 9 | "fps": 30, 10 | "subsample": 10, 11 | "is_depth": true, 12 | "is_stereo_images": true, 13 | "is_imu_enabled": true, 14 | "number_imu_records": 15, 15 | "disable_magnetometer_fusion": false, 16 | "mono_resolution": [1280, 800], 17 | "stereo_manual_exposure": [5000, 400], 18 | "stereo_manual_wb": 3000, 19 | 20 | "stereo_median_filter": "KERNEL_7x7", 21 | "stereo_mode": "HIGH_ACCURACY", 22 | "stereo_extended_disparity": false, 23 | "stereo_subpixel": false, 24 | "stereo_left_right_check": true 25 | } 26 | } 27 | }, 28 | "links": [] 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /config/test-opencv-camera.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "camera": { 6 | "driver": "osgar.drivers.opencv:LogOpenCVCamera", 7 | "in": [], 8 | "out": ["raw"], 9 | "init": { 10 | "port": 0, 11 | "sleep": 1.0 12 | } 13 | } 14 | }, 15 | "links": [] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /config/test-ouster_lidar-udp.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "lidar_udp": { 6 | "driver": "udp", 7 | "out": ["raw"], 8 | "init": { 9 | "host": "192.168.1.91", 10 | "port": 7502, 11 | "bufsize": 100000 12 | } 13 | }, 14 | "imu_udp": { 15 | "driver": "udp", 16 | "out": ["raw"], 17 | "init": { 18 | "host": "192.168.1.91", 19 | "port": 7503, 20 | "bufsize": 1024 21 | } 22 | }, 23 | "lidar_http": { 24 | "driver": "osgar.drivers.logsocket:LogHTTPRequest", 25 | "in": ["request"], 26 | "out": ["raw"], 27 | "init": { 28 | "output": true, 29 | "timeout": 1.0 30 | } 31 | }, 32 | 33 | "app": { 34 | "driver": "osgar.drivers.ouster_lidar:OusterLidarUDP", 35 | "in": ["udp_packet", "http_response"], 36 | "out": ["http_request"], 37 | "init": { 38 | "lidar_url": "http://192.168.1.91/api/v1/sensor/config", 39 | "config_params": { 40 | "lidar_mode": "512x10", 41 | "udp_profile_lidar": "LEGACY" 42 | } 43 | } 44 | } 45 | }, 46 | "links": [ 47 | ["lidar_udp.raw", "app.udp_packet"], 48 | ["lidar_http.raw", "app.response"], 49 | ["app.http_request", "lidar_http.request"] 50 | ] 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /config/test-pcan.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "can": { 6 | "driver": "pcan", 7 | "in": ["can"], 8 | "out": ["can"], 9 | "init": {} 10 | } 11 | }, 12 | "links": [] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /config/test-pozyx.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "pozyx": { 6 | "driver": "pozyx", 7 | "in": [], 8 | "out": ["range"], 9 | "init": { 10 | "port": "/dev/ttyACM0", 11 | "devices": ["0x6827"], 12 | "sensor": ["0x6827"], 13 | "gpio": ["0x6827"] 14 | } 15 | } 16 | }, 17 | "links": [] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /config/test-pull_zmq.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "pull": { 6 | "driver": "osgar.drivers.pull:Pull", 7 | "init": { 8 | "endpoint": "tcp://192.168.0.23:5557", 9 | "outputs": ["localized_artf", "debug_image"] 10 | } 11 | } 12 | }, 13 | "links": [] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /config/test-pulutof1.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "pulutof1": { 6 | "driver": "tcp", 7 | "in": ["raw"], 8 | "out": ["raw"], 9 | "init": { 10 | "host": "169.254.78.166", 11 | "port": 22222, 12 | "bufsize": 10000 13 | } 14 | } 15 | }, 16 | "links": [] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /config/test-qorvo.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "timer": { 6 | "driver": "timer", 7 | "init": { 8 | "sleep": 1.0 9 | } 10 | }, 11 | "qorvo": { 12 | "driver": "osgar.drivers.qorvo:Qorvo", 13 | "in": ["raw"], 14 | "out": ["range", "raw"], 15 | "init": { 16 | } 17 | }, 18 | "qserial": { 19 | "driver": "serial", 20 | "in": ["raw"], 21 | "out": ["raw"], 22 | "init": { 23 | "port": "/dev/ttyACM0", 24 | "speed": 115200 25 | } 26 | } 27 | }, 28 | "links": [ 29 | ["timer.tick", "qorvo.timer"], 30 | ["qorvo.raw", "qserial.raw"], 31 | ["qserial.raw", "qorvo.raw"] 32 | ] 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /config/test-realsense-D400.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "driver": "realsense", 7 | "init": { 8 | "device": "D400", 9 | "depth_subsample": 3, 10 | "depth_rgb": true, 11 | "depth_resolution": [640, 360], 12 | "rgb_resolution": [640, 360], 13 | "depth_fps": 30 14 | } 15 | } 16 | }, 17 | "links": [] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /config/test-realsense-L500.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "driver": "realsense", 7 | "init": { 8 | "device": "L500", 9 | "depth_subsample": 6, 10 | "depth_rgb": true, 11 | "depth_infra": true, 12 | "depth_resolution": [1024, 768], 13 | "rgb_resolution": [1280, 720], 14 | "depth_fps": 30 15 | } 16 | } 17 | }, 18 | "links": [] 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /config/test-realsense-T200.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "driver": "realsense", 7 | "init": { 8 | "device": "T200", 9 | "pose_subsample": 20 10 | } 11 | } 12 | }, 13 | "links": [] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /config/test-replay-node.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "replay": { 6 | "driver": "replay", 7 | "in": [], 8 | "out": ["pose2d", "scan", "jpeg", "rotation"], 9 | "init": { 10 | "filename": "d:\\md\\osgar\\logs\\subt\\eduro\\190305\\wall-190305_203603.log", 11 | "pins": { 12 | "eduro.pose2d": "pose2d", 13 | "lidar.scan": "scan", 14 | "imu.rot": "rotation", 15 | "camera.raw": "jpeg" 16 | } 17 | } 18 | } 19 | }, 20 | "links": [] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /config/test-spider-gps-imu.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "gps": { 6 | "driver": "gps", 7 | "in": ["raw"], 8 | "out": ["position", "rel_position"], 9 | "init": {} 10 | }, 11 | "gps_serial": { 12 | "driver": "serial", 13 | "in": [], 14 | "out": ["raw"], 15 | "init": {"port": "/dev/ttyACM0", "speed": 115200} 16 | }, 17 | "imu": { 18 | "driver": "imu", 19 | "in": ["raw"], 20 | "out": ["orientation"], 21 | "init": {} 22 | }, 23 | "imu_serial": { 24 | "driver": "serial", 25 | "in": [], 26 | "out": ["raw"], 27 | "init": {"port": "/dev/ttyUSB0", "speed": 115200} 28 | }, 29 | "spider": { 30 | "driver": "spider", 31 | "in": ["raw"], 32 | "out": ["can"], 33 | "init": {} 34 | }, 35 | "spider_serial": { 36 | "driver": "serial", 37 | "in": ["raw"], 38 | "out": ["raw"], 39 | "init": {"port": "/dev/ttyS0", "speed": 115200, 40 | "rtscts":true, "reset":true} 41 | } 42 | }, 43 | "links": [["gps_serial.raw", "gps.raw"], 44 | ["imu_serial.raw", "imu.raw"], 45 | ["spider_serial.raw", "spider.raw"], 46 | ["spider.can", "spider_serial.raw"]] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /config/test-spider.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "spider": { 6 | "driver": "spider", 7 | "in": ["can"], 8 | "out": ["can"], 9 | "init": {} 10 | }, 11 | "can": { 12 | "driver": "can", 13 | "in": ["raw", "can"], 14 | "out": ["can", "raw"], 15 | "init": {"canopen": true} 16 | }, 17 | "serial": { 18 | "driver": "serial", 19 | "in": ["raw"], 20 | "out": ["raw"], 21 | "init": {"port": "/dev/ttyS0", "speed": 115200, 22 | "rtscts":true, "reset":true} 23 | } 24 | }, 25 | "links": [["spider.can", "can.can"], 26 | ["can.can", "spider.can"], 27 | ["serial.raw", "can.raw"], 28 | ["can.raw", "serial.raw"]] 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /config/test-system-monitor.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "driver": "systemmonitor", 7 | "in": [], 8 | "out": ["cpu", "ram", "temp"], 9 | "init": { 10 | "dmesg": true 11 | } 12 | } 13 | }, 14 | "links": [] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /config/test-usb-camera.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "camera-notebook": { 6 | "driver": "usbcam", 7 | "in": [], 8 | "out": ["jpg"], 9 | "init": { 10 | "bus": 1, 11 | "ports": [5], 12 | "sleep": 0.1 13 | } 14 | }, 15 | "camera-kayeton": { 16 | "driver": "usbcam", 17 | "in": [], 18 | "out": ["jpg"], 19 | "init": { 20 | "bus": 1, 21 | "ports": [3], 22 | "sleep": 0.1 23 | } 24 | } 25 | }, 26 | "links": [] 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /config/test-usb-lidar.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "lidar": { 6 | "driver": "lidar", 7 | "in": ["raw"], 8 | "out": ["raw", "scan"], 9 | "init": { 10 | "sleep": 0.1 11 | } 12 | }, 13 | "lidar_usb": { 14 | "driver": "usb", 15 | "in": [], 16 | "out": ["raw"], 17 | "init": {} 18 | } 19 | }, 20 | "links": [["lidar_usb.raw", "lidar.raw"], 21 | ["lidar.raw", "lidar_usb.raw"]] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /config/test-vanjee-lidar.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "vanjee": { 6 | "driver": "vanjee", 7 | "in": ["raw"], 8 | "out": ["raw", "xyz"], 9 | "init": {} 10 | }, 11 | "vanjee_udp": { 12 | "driver": "udp", 13 | "in": ["raw"], 14 | "out": ["raw"], 15 | "init": {"host": "192.168.0.2", "port": 6050, "timeout": 3.0, "bufsize": 100000} 16 | } 17 | }, 18 | "links": [["vanjee_udp.raw", "vanjee.raw"], 19 | ["vanjee.raw", "vanjee_udp.raw"] 20 | ] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /config/test-velodyne.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "velodyne": { 6 | "driver": "velodyne", 7 | "in": ["raw"], 8 | "out": ["raw", "xyz"], 9 | "init": {} 10 | }, 11 | "velodyne_udp": { 12 | "driver": "udp", 13 | "in": ["raw"], 14 | "out": ["raw"], 15 | "init": {"host": "192.168.1.201", "port": 2368, "timeout": 3.0, "bufsize": 100000} 16 | } 17 | }, 18 | "links": [["velodyne_udp.raw", "velodyne.raw"], 19 | ["velodyne.raw", "velodyne_udp.raw"] 20 | ] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /config/test-vesc.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "vesc": { 6 | "driver": "vesc", 7 | "in": ["can"], 8 | "out": ["can"], 9 | "init": {} 10 | }, 11 | "can": { 12 | "driver": "pcan", 13 | "in": ["can"], 14 | "out": ["can"], 15 | "init": {} 16 | } 17 | }, 18 | "links": [["can.can", "vesc.can"], 19 | ["vesc.can", "can.can"]] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /config/test-wifiscan.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "wifi": { 6 | "driver": "subt.wifisignal:WifiSignal", 7 | "in": [], 8 | "out": ["wifiscan"], 9 | "init": { 10 | "sleep": 1.0, 11 | "interface": "wlp5s0" 12 | } 13 | } 14 | }, 15 | "links": [] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /config/test-windows-gps.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "gps": { 6 | "driver": "gps", 7 | "in": ["raw"], 8 | "out": ["position"], 9 | "init": {} 10 | }, 11 | "gps_serial": { 12 | "driver": "serial", 13 | "in": [], 14 | "out": ["raw"], 15 | "init": {"port": "COM5", "speed": 4800} 16 | } 17 | }, 18 | "links": [["gps_serial.raw", "gps.raw"]] 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /config/test-winsen-gas-detector.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "gas_detector": { 6 | "driver": "osgar.drivers.winsen_gas_detector:WinsenCO2", 7 | "in": ["raw", "trigger"], 8 | "out": ["raw", "co2"], 9 | "init": {} 10 | }, 11 | "serial": { 12 | "driver": "serial", 13 | "in": ["raw"], 14 | "out": ["raw"], 15 | "init": {"port": "/dev/mh_z19", "speed": 9600} 16 | }, 17 | "timer": { 18 | "driver": "timer", 19 | "in": [], 20 | "out": ["tick"], 21 | "init": {"sleep": 1.0} 22 | } 23 | }, 24 | "links": [ 25 | ["serial.raw", "gas_detector.raw"], 26 | ["gas_detector.raw", "serial.raw"], 27 | ["timer.tick", "gas_detector.trigger"] 28 | ] 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /config/test-zeromq.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "zeromq": { 6 | "driver": "zeromq", 7 | "in": [], 8 | "out": ["raw"], 9 | "init": { 10 | "mode": "PULL", 11 | "endpoint": "tcp://localhost:5555" 12 | } 13 | } 14 | }, 15 | "links": [] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /config/zeromq-fwd.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "receiver": { 6 | "driver": "zeromq", 7 | "in": [], 8 | "out": ["raw"], 9 | "init": { 10 | "mode": "PULL", 11 | "endpoint": "tcp://localhost:5555" 12 | } 13 | }, 14 | "transmitter": { 15 | "driver": "zeromq", 16 | "in": [], 17 | "out": ["raw"], 18 | "init": { 19 | "mode": "PUSH", 20 | "endpoint": "tcp://localhost:5556" 21 | } 22 | } 23 | }, 24 | "links": [["receiver.raw", "transmitter.raw"]] 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /doc/sphinx/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = python -msphinx 7 | SPHINXPROJ = osgar 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /doc/sphinx/can.rst: -------------------------------------------------------------------------------- 1 | CAN Bus Bridge 2 | ============== 3 | 4 | "CAN Bus Bridge" is used for communication between PC serial port and CAN 5 | bus network. The module was developed and manufactured by RobSys.cz 6 | 7 | Communication Protocol 8 | ---------------------- 9 | 10 | The bridge is in configuration mode after power up (or application of "RESET" 11 | via Serial.setDTR(0)). This is reported once via set of 0xFF bytes followed 12 | by 0xFE 0x10 packets. After that is bridge waiting for "sync" via ten 0xFF 13 | bytes. 14 | 15 | You can configure CAN bridge parameters after "sync" with bridge. For example 16 | to set CAN communication speed to 1Mb use 0xFE 0x57. 17 | 18 | Once you are finished with configuration you can switch mode to operational 19 | via 0xFE 0x31. The bridge starts to listen on CAN bus and forward all available 20 | (or selected, if configured) messages to PC via serial port. 21 | 22 | -------------------------------------------------------------------------------- /doc/sphinx/drivers.rst: -------------------------------------------------------------------------------- 1 | Drivers 2 | ======= 3 | 4 | The "drivers" directory contains implementation of all drivers for various 5 | devices. Sensors, effectors as well as the mobile platforms are included. 6 | The driver takes care of a single device, or better to say a single 7 | communication stream (serial.Serial for example). The data are collected, 8 | logged and parsed for further processing. 9 | 10 | Logging 11 | ------- 12 | 13 | There is at least one stream logged per driver - the input for sensors and 14 | the output for effectors. If bidirectional communication is required then 15 | both streams are logged. The "stream ID" is part of the driver configuration. 16 | 17 | Use cases 18 | --------- 19 | 20 | There are two basic use cases: real run and replay. In real run real port 21 | is opened and dedicated Thread::run() takes care of reading data with timeout 22 | and the processing. 23 | 24 | In the "replay" mode the run is single-threaded and the processing is 25 | simulated from logged data. This mode is mainly designed for debugging, 26 | development of parsers and also verification of identical outputs on 27 | different platforms (robot PC vs. notebook for example). 28 | 29 | 30 | -------------------------------------------------------------------------------- /doc/sphinx/glossary.rst: -------------------------------------------------------------------------------- 1 | Glossary 2 | ======== 3 | 4 | .. glossary:: 5 | 6 | bus 7 | The communication backbone, providing `publish` and `listen` operations. 8 | The bus takes care of sequencing all messages within the sysem and 9 | serialization via logging facility. 10 | 11 | link 12 | Directed connection of two nodes. The source node generates messages by 13 | `publish` call and the destinaion node accepts them via `listen` call. 14 | 15 | logfile 16 | Binary file containing message data with their source and timestamp. 17 | 18 | node 19 | The basic processing unit attached to `bus`. It has fixed set of inputs 20 | and outputs. Some nodes implement communication with outer world like TCP. 21 | 22 | OSGAR 23 | Open Source Garden/Generic Autonomous Robot (Python library) 24 | 25 | robot 26 | The collection of interacting `nodes` via `bus`. This typically corresponds 27 | to a machine with set of sensors and efectors in the real world. 28 | 29 | stream 30 | Output from node without specified destination like for `link`. 31 | 32 | timestamp 33 | Python `datetime.timedelta` with microsecond precision starting from zero 34 | with the beginning of the program. 35 | 36 | -------------------------------------------------------------------------------- /doc/sphinx/index.rst: -------------------------------------------------------------------------------- 1 | .. osgar documentation master file, created by 2 | sphinx-quickstart on Sun Oct 28 10:25:10 2018. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to osgar's documentation! 7 | ================================= 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | :caption: Contents: 12 | 13 | logging 14 | eduro 15 | drivers 16 | rosproxy 17 | can 18 | msgtypes 19 | glossary 20 | 21 | Indices and tables 22 | ================== 23 | 24 | * :ref:`genindex` 25 | * :ref:`modindex` 26 | * :ref:`search` 27 | -------------------------------------------------------------------------------- /doc/sphinx/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=python -msphinx 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | set SPHINXPROJ=osgar 13 | 14 | if "%1" == "" goto help 15 | 16 | %SPHINXBUILD% >NUL 2>NUL 17 | if errorlevel 9009 ( 18 | echo. 19 | echo.The Sphinx module was not found. Make sure you have Sphinx installed, 20 | echo.then set the SPHINXBUILD environment variable to point to the full 21 | echo.path of the 'sphinx-build' executable. Alternatively you may add the 22 | echo.Sphinx directory to PATH. 23 | echo. 24 | echo.If you don't have Sphinx installed, grab it from 25 | echo.http://sphinx-doc.org/ 26 | exit /b 1 27 | ) 28 | 29 | sphinx-apidoc -o . ..\..\osgar 30 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 31 | goto end 32 | 33 | :help 34 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 35 | 36 | :end 37 | popd 38 | -------------------------------------------------------------------------------- /doc/sphinx/rosproxy.rst: -------------------------------------------------------------------------------- 1 | ROS Proxy 2 | ========= 3 | 4 | The node `rosproxy` is an interface to `ROS `_ (Robot 5 | Operating System). The implementation is based on `experiments with robot Husky 6 | `_ back in 2014. The technical info 7 | is taken from `ROS Technical Overview 8 | `_. `Hello World 9 | `_ and `ROS 10 | Practical Example `_ are good 11 | starting points to get familiar with the basic ROS concept. 12 | 13 | Note, that OSGAR ROS Proxy implementation does not require compilation and 14 | specific operating system (typically Ubuntu linux). The price is then limited 15 | set of available messages (compatible with OSGAR), but they can be extended in 16 | the future. 17 | 18 | OSGAR ROS Proxy is a node both in OSGAR as well as ROS sense. It connects to 19 | ROS master, provides XMLRPC server for topic registration and finally it 20 | communicates over TCP in order to send and receive messages. In some sense it 21 | is actually bridge between these two worlds. 22 | 23 | Every OSGAR ROS Proxy node configuration needs: 24 | - ROS Master URI 25 | - ROS Client URI, i.e. configuration for XMLRPC server 26 | - topic and if it should be published or subscribed 27 | 28 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | Examples of OSGAR usage 2 | ======================= 3 | 4 | This is place for some examples of robot and scenarios where OSGAR was used. 5 | 6 | Create your own robot driver (myrobot) 7 | -------------------------------------- 8 | 9 | This example demonstrates how to extend existing OSGAR to support also your 10 | specific robot. Here only simple simulation is used so it should run without 11 | need to have any extra hardware. 12 | 13 | 14 | SICK Robot Day 2018 (sick2018) 15 | ------------------------------ 16 | 17 | The German manufacture of LIDARs (laser scanner SICK) organizes every two years 18 | competition in Waldkirch/Germany. The company provides testing samples of 19 | sensors to participating universities. In 2018 it was TiM 571. 20 | 21 | Robot Eduro was equipped with lidar, camera and hand with magnets to collect 22 | red metal balls. This example contains code used in the 2nd run, where Eduro 23 | scored 3 balls and finished on the 3rd place in the competition. 24 | 25 | For more information see: 26 | https://robotika.cz/competitions/sick-robot-day/2018/ 27 | 28 | -------------------------------------------------------------------------------- /examples/accumulator/accumulator.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "processor": { 6 | "driver": "accumulator:Processor", 7 | "in": ["map"], 8 | "out": ["request"], 9 | "init": {} 10 | }, 11 | "accumulator": { 12 | "driver": "accumulator:Accumulator", 13 | "in": ["xyz", "request"], 14 | "out": ["map"], 15 | "init": {} 16 | }, 17 | "velodyne": { 18 | "driver": "velodyne", 19 | "in": ["raw"], 20 | "out": ["raw", "xyz"], 21 | "init": { 22 | "offset_step": 100 23 | } 24 | }, 25 | "velodyne_udp": { 26 | "driver": "udp", 27 | "in": ["raw"], 28 | "out": ["raw"], 29 | "init": {"host": "192.168.1.201", "port": 2368, "timeout": 3.0, "bufsize": 100000} 30 | } 31 | }, 32 | "links": [["velodyne_udp.raw", "velodyne.raw"], 33 | ["velodyne.raw", "velodyne_udp.raw"], 34 | ["velodyne.xyz", "accumulator.xyz"], 35 | ["processor.request", "accumulator.request"], 36 | ["accumulator.map", "processor.map"] 37 | ] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/accumulator/accumulator.py: -------------------------------------------------------------------------------- 1 | """ 2 | Example of a simple application collecting map data 3 | """ 4 | from osgar.node import Node 5 | from osgar.bus import BusShutdownException 6 | 7 | 8 | class Processor(Node): 9 | def __init__(self, config, bus): 10 | super().__init__(config, bus) 11 | 12 | def on_map(self, data): 13 | print(self.time, len(self.map)) 14 | self.sleep(0.2) # simulate some work here 15 | self.publish('request', True) 16 | 17 | def run(self): 18 | try: 19 | self.publish('request', True) 20 | while True: 21 | self.update() 22 | except BusShutdownException: 23 | pass 24 | 25 | 26 | class Accumulator(Node): 27 | def __init__(self, config, bus): 28 | super().__init__(config, bus) 29 | self.map_data = [] 30 | 31 | def on_request(self, data): 32 | self.publish('map', self.map_data[:]) 33 | 34 | def on_xyz(self, data): 35 | self.map_data.extend(data) 36 | self.map_data = self.map_data[-100:] # keep last 100 points 37 | 38 | # vim: expandtab sw=4 ts=4 39 | -------------------------------------------------------------------------------- /examples/gym/configs/config_example_map.yaml: -------------------------------------------------------------------------------- 1 | # metadata 2 | run_name: 'map_wide' 3 | # characteristic number for map 4 | perf_num: 6 5 | 6 | # map paths 7 | map_path: './configs/example_map' 8 | map_ext: '.png' 9 | 10 | # starting pose for map 11 | sx: 0.0 12 | sy: 0.0 13 | stheta: 1.37079632679 14 | 15 | # varied params bound 16 | # physical params 17 | mass_min: 3.0 18 | mass_max: 4.0 19 | lf_min: 0.147 20 | lf_max: 0.170 21 | # controller params 22 | tlad_min: 0.2 23 | tlad_max: 5. 24 | vgain_min: 0.5 25 | vgain_max: 1.5 26 | 27 | # computation budget (can think of it as gen_num times pop_size) 28 | popsize: 100 29 | budget: 1000 30 | 31 | # optimization method 32 | optim_method: 'CMA' 33 | 34 | # seed 35 | seed: 12345 36 | -------------------------------------------------------------------------------- /examples/gym/configs/config_example_map2.yaml: -------------------------------------------------------------------------------- 1 | # metadata 2 | run_name: 'playground' 3 | # characteristic number for map 4 | perf_num: 7 5 | 6 | # map paths 7 | map_path: './configs/example_map2' 8 | map_ext: '.png' 9 | 10 | # starting pose for map 11 | sx: 0.0 12 | sy: 0.0 13 | stheta: 3.1415 14 | 15 | 16 | # varied params bound 17 | # physical params 18 | mass_min: 3.0 19 | mass_max: 4.0 20 | lf_min: 0.147 21 | lf_max: 0.170 22 | # controller params 23 | tlad_min: 0.2 24 | tlad_max: 5. 25 | vgain_min: 0.5 26 | vgain_max: 1.5 27 | 28 | # computation budget (can think of it as gen_num times pop_size) 29 | popsize: 100 30 | budget: 1000 31 | 32 | # optimization method 33 | optim_method: 'CMA' 34 | 35 | # seed 36 | seed: 12345 37 | -------------------------------------------------------------------------------- /examples/gym/configs/example_map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotika/osgar/ab10ba4004329dcc0ea1ffc68ac2334bb1995c38/examples/gym/configs/example_map.png -------------------------------------------------------------------------------- /examples/gym/configs/example_map.yaml: -------------------------------------------------------------------------------- 1 | image: configs/example_map.png 2 | resolution: 0.062500 3 | origin: [-78.21853769831466,-44.37590462453829, 0.000000] 4 | negate: 0 5 | occupied_thresh: 0.45 6 | free_thresh: 0.196 7 | -------------------------------------------------------------------------------- /examples/gym/configs/example_map2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotika/osgar/ab10ba4004329dcc0ea1ffc68ac2334bb1995c38/examples/gym/configs/example_map2.png -------------------------------------------------------------------------------- /examples/gym/configs/example_map2.yaml: -------------------------------------------------------------------------------- 1 | image: configs/example_map2.png 2 | resolution: 0.05 3 | origin: [-11.0, -7.5, 0.000000] 4 | negate: 0 5 | occupied_thresh: 0.45 6 | free_thresh: 0.196 7 | -------------------------------------------------------------------------------- /examples/gym/configs/race-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "race": { 6 | "driver": "examples.gym.my_race:MyRace", 7 | "in": ["pose2d", "scan"], 8 | "out": ["desired_steering"], 9 | "init": { 10 | "max_speed": 4 11 | } 12 | }, 13 | "gym": { 14 | "driver": "examples.gym.gym_simulator:GymSimulator", 15 | "in": ["desired_steering", "tick"], 16 | "out": ["pose2d", "tick"], 17 | "init": { 18 | "map_config": "configs/config_example_map.yaml" 19 | } 20 | }, 21 | "tick": { 22 | "driver": "timer", 23 | "in": [], 24 | "out": ["tick"], 25 | "init": { 26 | "sleep": 0.02 27 | } 28 | } 29 | }, 30 | "links": [["race.desired_steering", "gym.desired_steering"], 31 | ["tick.tick", "gym.tick"], 32 | ["gym.pose2d", "race.pose2d"], 33 | ["gym.scan", "race.scan"] 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /examples/gym/configs/test-gym_simulation.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "driver": "osgar.go:Go", 7 | "in": ["pose2d", "scan"], 8 | "out": ["desired_speed"], 9 | "init": { 10 | "max_speed": 1.0, 11 | "desired_angle": 0, 12 | "dist": 1, 13 | "timeout": 10 14 | } 15 | }, 16 | "gym": { 17 | "driver": "examples.gym.gym_simulator:GymSimulator", 18 | "in": ["desired_steering", "tick"], 19 | "out": ["pose2d", "tick"], 20 | "init": { 21 | "map_config": "configs/config_example_map.yaml" 22 | } 23 | }, 24 | "tick": { 25 | "driver": "timer", 26 | "in": [], 27 | "out": ["tick"], 28 | "init": { 29 | "sleep": 0.02 30 | } 31 | } 32 | }, 33 | "links": [["app.desired_speed", "gym.desired_steering"], 34 | ["tick.tick", "gym.tick"], 35 | ["gym.pose2d", "app.pose2d"]] 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /examples/myrobot/myrobot-slots.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "driver": "application", 7 | "in": ["emergency_stop", "pose2d"], 8 | "out": ["desired_speed"], 9 | "init": { 10 | "max_speed": 0.5 11 | } 12 | }, 13 | "myrobot": { 14 | "driver": "myrobot:MyRobot", 15 | "in": ["slot_desired_speed"], 16 | "out": ["emergency_stop", "pose2d"], 17 | "init": {} 18 | }, 19 | "timer": { 20 | "driver": "myrobot:MyTimer", 21 | "in": [], 22 | "out": ["tick"], 23 | "init": { 24 | "sleep": 0.1 25 | } 26 | } 27 | }, 28 | "links": [["app.desired_speed", "myrobot.slot_desired_speed"], 29 | ["myrobot.emergency_stop", "app.emergency_stop"], 30 | ["myrobot.pose2d", "app.pose2d"], 31 | ["timer.tick", "myrobot.tick"]] 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/myrobot/myrobot.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "driver": "application", 7 | "in": ["emergency_stop", "pose2d"], 8 | "out": ["desired_speed"], 9 | "init": { 10 | "max_speed": 0.5 11 | } 12 | }, 13 | "myrobot": { 14 | "driver": "myrobot:MyRobot", 15 | "in": ["desired_speed"], 16 | "out": ["emergency_stop", "pose2d"], 17 | "init": {} 18 | }, 19 | "timer": { 20 | "driver": "myrobot:MyTimer", 21 | "in": [], 22 | "out": ["tick"], 23 | "init": { 24 | "sleep": 0.1 25 | } 26 | } 27 | }, 28 | "links": [["app.desired_speed", "myrobot.desired_speed"], 29 | ["myrobot.emergency_stop", "app.emergency_stop"], 30 | ["myrobot.pose2d", "app.pose2d"], 31 | ["timer.tick", "myrobot.tick"]] 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /moon/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from osgar.lib import create_load_tests 4 | load_tests = create_load_tests(__file__) 5 | -------------------------------------------------------------------------------- /moon/docker/rover/entrypoint.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | source /rover_workspace/devel/setup.bash 5 | 6 | exec "$@" 7 | -------------------------------------------------------------------------------- /moon/docker/rover/rosconsole.config: -------------------------------------------------------------------------------- 1 | # 2 | # rosconsole will find this file by default at $ROS_ROOT/config/rosconsole.config 3 | # 4 | # You can define your own by e.g. copying this file and setting 5 | # ROSCONSOLE_CONFIG_FILE (in your environment) to point to the new file 6 | # 7 | log4j.logger.ros=DEBUG 8 | log4j.logger.ros.roscpp.superdebug=WARN 9 | log4j.logger.ros.roscpp.cached_parameters=INFO 10 | -------------------------------------------------------------------------------- /moon/howto.md: -------------------------------------------------------------------------------- 1 | In one terminal start simulation: 2 | 3 | git/srcp2-competitors$ docker/scripts/launch/roslaunch_docker --run-round 1 -n 4 | (-n = no GUI does not work at the moment, because it does not start the simulation, i.e. this is "for later") 5 | 6 | In the second terminal first build image: 7 | git/osgar/moon/docker$ ./build.bash rover 8 | 9 | and then run it: 10 | docker run --network=host -it --rm rover:latest 11 | 12 | Note, that you can also use interactive way via: 13 | docker run --network=host -it --rm rover:latest /bin/bash 14 | 15 | -------------------------------------------------------------------------------- /moon/moon-view.bat: -------------------------------------------------------------------------------- 1 | python -m osgar.tools.lidarview --pose2d app.pose2d --lidar rosmsg.scan --camera rosmsg.left_image --camera2 rosmsg.right_image --lidar-limit 20000 --window-size 1200 660 --title rosmsg.rot %* 2 | -------------------------------------------------------------------------------- /moon/moon-view.sh: -------------------------------------------------------------------------------- 1 | python3 -m osgar.tools.lidarview --pose2d app.pose2d --lidar rosmsg.scan --camera rosmsg.left_image --camera2 rosmsg.right_image --lidar-limit 20000 --window-size 1200 660 --title rosmsg.rot $1 2 | -------------------------------------------------------------------------------- /moon/motorpid.py: -------------------------------------------------------------------------------- 1 | """ 2 | Motor PID controller 3 | """ 4 | 5 | class MotorPID: 6 | def __init__(self, p=1, i=0, d=0): 7 | self.desired_speed = 0.0 8 | self.current_speed = 0.0 9 | self.param_p = p 10 | 11 | def set_desired_speed(self, speed): 12 | self.desired_speed = speed 13 | 14 | def update(self, current_speed): 15 | self.current_speed = current_speed 16 | 17 | def get_effort(self): 18 | err = self.desired_speed - self.current_speed 19 | return self.param_p * err 20 | 21 | # vim: expandtab sw=4 ts=4 22 | -------------------------------------------------------------------------------- /moon/ros_launchfiles/qual_round_1.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /moon/ros_launchfiles/qual_round_2.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /moon/ros_launchfiles/qual_round_3.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /moon/rospy/rospy_excavator_round2.py: -------------------------------------------------------------------------------- 1 | """ 2 | Proxy for ROS sensors and effectors 3 | this is Python 2.7 code 4 | """ 5 | 6 | import sys 7 | import rospy 8 | import yaml 9 | 10 | from rospy_excavator import RospyExcavator, RospyExcavatorReqRep, RospyExcavatorPushPull 11 | from rospy_round2 import RospyRound2, RospyRound2ReqRep, RospyRound2PushPull 12 | 13 | from srcp2_msgs.srv import Qual2VolatilesSrv 14 | 15 | class RospyExcavatorRound2PushPull(RospyExcavatorPushPull, RospyRound2PushPull): 16 | pass 17 | 18 | class RospyExcavatorRound2ReqRep(RospyExcavatorReqRep, RospyRound2ReqRep): 19 | pass 20 | 21 | class RospyExcavatorRound2(RospyExcavator, RospyRound2): 22 | pass 23 | 24 | if __name__ == '__main__': 25 | rs = RospyExcavatorRound2() 26 | rs.launch(RospyExcavatorRound2PushPull, RospyExcavatorRound2ReqRep, sys.argv[1:]) 27 | 28 | # vim: expandtab sw=4 ts=4 29 | -------------------------------------------------------------------------------- /moon/rospy/rospy_hauler.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | """ 3 | Proxy for ROS sensors and effectors 4 | this is Python 2.7 code 5 | """ 6 | 7 | import sys 8 | import rospy 9 | 10 | from rospy_rover import RospyRover, RospyRoverReqRep, RospyRoverPushPull 11 | from srcp2_msgs.msg import HaulerMsg 12 | 13 | class RospyHaulerPushPull(RospyRoverPushPull): 14 | 15 | def register_handlers(self): 16 | super(RospyHaulerPushPull, self).register_handlers() 17 | rospy.Subscriber('/' + self.robot_name + '/bin_info', HaulerMsg, self.callback_topic, '/' + self.robot_name + '/bin_info') 18 | 19 | class RospyHaulerReqRep(RospyRoverReqRep): 20 | pass 21 | 22 | class RospyHauler(RospyRover): 23 | pass 24 | 25 | if __name__ == '__main__': 26 | rh = RospyHauler() 27 | rh.launch(RospyHaulerPushPull, RospyHaulerReqRep, sys.argv[1:]) 28 | 29 | # vim: expandtab sw=4 ts=4 30 | -------------------------------------------------------------------------------- /moon/rospy/rospy_hauler_round2.py: -------------------------------------------------------------------------------- 1 | """ 2 | Proxy for ROS sensors and effectors 3 | this is Python 2.7 code 4 | """ 5 | 6 | import sys 7 | import rospy 8 | import yaml 9 | 10 | from rospy_hauler import RospyHauler, RospyHaulerReqRep, RospyHaulerPushPull 11 | from rospy_round2 import RospyRound2, RospyRound2ReqRep, RospyRound2PushPull 12 | 13 | class RospyHaulerRound2PushPull(RospyHaulerPushPull, RospyRound2PushPull): 14 | pass 15 | 16 | class RospyHaulerRound2ReqRep(RospyHaulerReqRep, RospyRound2ReqRep): 17 | pass 18 | 19 | class RospyHaulerRound2(RospyHauler, RospyRound2): 20 | pass 21 | 22 | 23 | if __name__ == '__main__': 24 | rs = RospyHaulerRound2() 25 | rs.launch(RospyHaulerRound2PushPull, RospyHaulerRound2ReqRep, sys.argv[1:]) 26 | 27 | # vim: expandtab sw=4 ts=4 28 | -------------------------------------------------------------------------------- /moon/rospy/rospy_round1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | """ 3 | Wait for all necessary ROS sensors 4 | this is Python 2.7 code 5 | """ 6 | 7 | from functools import partial 8 | 9 | import rospy 10 | from rospy_base import RospyBase, RospyBaseReqRep, RospyBasePushPull 11 | 12 | # SRCP2 specific 13 | from srcp2_msgs.msg import Qual1ScoringMsg 14 | 15 | 16 | class RospyRound1PushPull(RospyBasePushPull): 17 | 18 | def register_handlers(self): 19 | super(RospyRound1PushPull, self).register_handlers() 20 | 21 | rospy.Subscriber('/qual_1_score', Qual1ScoringMsg, partial(self.callback_topic, rate=50), '/qual_1_score') 22 | 23 | class RospyRound1ReqRep(RospyBaseReqRep): 24 | pass 25 | 26 | class RospyRound1Helper(RospyBase): 27 | pass 28 | 29 | class RospyRound1(RospyRound1Helper): 30 | pass 31 | 32 | 33 | # vim: expandtab sw=4 ts=4 34 | -------------------------------------------------------------------------------- /moon/rospy/rospy_scout.py: -------------------------------------------------------------------------------- 1 | """ 2 | Proxy for ROS sensors and effectors 3 | this is Python 2.7 code 4 | """ 5 | 6 | import sys 7 | import rospy 8 | 9 | from rospy_rover import RospyRover, RospyRoverReqRep, RospyRoverPushPull 10 | from srcp2_msgs.msg import VolSensorMsg 11 | 12 | 13 | class RospyScoutPushPull(RospyRoverPushPull): 14 | def __init__(self, argv): 15 | super(RospyScoutPushPull, self).__init__(argv) 16 | 17 | def register_handlers(self): 18 | super(RospyScoutPushPull, self).register_handlers() 19 | 20 | rospy.Subscriber('/' + self.robot_name + '/volatile_sensor', VolSensorMsg, self.callback_topic, '/' + self.robot_name + '/volatile_sensor') 21 | 22 | class RospyScoutReqRep(RospyRoverReqRep): 23 | pass 24 | 25 | class RospyScout(RospyRover): 26 | pass 27 | 28 | if __name__ == '__main__': 29 | rs = RospyScout() 30 | rs.launch(RospyScoutPushPull, RospyScoutReqRep, sys.argv[1:]) 31 | -------------------------------------------------------------------------------- /moon/rospy/rospy_scout_round3.py: -------------------------------------------------------------------------------- 1 | """ 2 | Proxy for ROS sensors and effectors 3 | this is Python 2.7 code 4 | 5 | scout enhanced with reporting detection of volatiles (task specific to Round 1 of Qualification) 6 | """ 7 | 8 | import sys 9 | import rospy 10 | 11 | from rospy_scout import RospyScout, RospyScoutReqRep, RospyScoutPushPull 12 | from rospy_round3 import RospyRound3, RospyRound3ReqRep, RospyRound3PushPull 13 | 14 | from srcp2_msgs.msg import Qual3ScoringMsg 15 | from srcp2_msgs.srv import Qual3ScoreSrv 16 | from geometry_msgs.msg import Point 17 | 18 | class RospyScoutRound3PushPull(RospyScoutPushPull, RospyRound3PushPull): 19 | pass 20 | 21 | class RospyScoutRound3ReqRep(RospyRound3ReqRep, RospyScoutReqRep): 22 | pass 23 | 24 | class RospyScoutRound3(RospyScout, RospyRound3): 25 | pass 26 | 27 | if __name__ == '__main__': 28 | rs = RospyScoutRound3() 29 | rs.launch(RospyScoutRound3PushPull, RospyScoutRound3ReqRep, sys.argv[1:]) 30 | -------------------------------------------------------------------------------- /moon/test_controller_round1.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from unittest.mock import MagicMock 3 | from datetime import timedelta 4 | 5 | from osgar.bus import Bus 6 | 7 | from moon.controller_round1 import SpaceRoboticsChallengeRound1 8 | 9 | 10 | class SpaceRoboticsChallengeRound1Test(unittest.TestCase): 11 | 12 | def test_usage(self): 13 | config = {} 14 | bus = Bus(MagicMock(write=MagicMock(return_value=timedelta()))) 15 | r1 = SpaceRoboticsChallengeRound1(config, bus=bus.handle('app')) 16 | r1.start() 17 | r1.request_stop() 18 | r1.join() 19 | 20 | # vim: expandtab sw=4 ts=4 21 | 22 | -------------------------------------------------------------------------------- /moon/test_data/basemarker.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotika/osgar/ab10ba4004329dcc0ea1ffc68ac2334bb1995c38/moon/test_data/basemarker.jpg -------------------------------------------------------------------------------- /moon/test_data/cube_homebase.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotika/osgar/ab10ba4004329dcc0ea1ffc68ac2334bb1995c38/moon/test_data/cube_homebase.jpg -------------------------------------------------------------------------------- /moon/test_motorpid.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from moon.motorpid import MotorPID 4 | 5 | 6 | class MotorPIDTest(unittest.TestCase): 7 | 8 | def test_pid(self): 9 | pid = MotorPID(p=1, i=0, d=0) 10 | pid.set_desired_speed(0.5) 11 | pid.update(current_speed=0) 12 | effort = pid.get_effort() 13 | self.assertEqual(effort, 0.5) 14 | 15 | 16 | # vim: expandtab sw=4 ts=4 17 | 18 | -------------------------------------------------------------------------------- /moon/vehicles/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from osgar.lib import create_load_tests 4 | load_tests = create_load_tests(__file__) 5 | -------------------------------------------------------------------------------- /moon/vehicles/hauler.py: -------------------------------------------------------------------------------- 1 | """ 2 | Moon Hauler Driver 3 | """ 4 | 5 | # source: (limited access) 6 | # https://gitlab.com/scheducation/srcp2-competitors/-/wikis/Documentation/API/Simulation_API 7 | 8 | # Hauler Bin 9 | # /hauler_n/bin_joint_controller/command 10 | 11 | # Info 12 | # /hauler_n/bin_info 13 | 14 | 15 | import math 16 | from osgar.lib.mathex import normalizeAnglePIPI 17 | 18 | from osgar.node import Node 19 | from moon.vehicles.rover import Rover 20 | 21 | class Hauler(Rover): 22 | def __init__(self, config, bus): 23 | super().__init__(config, bus) 24 | 25 | # vim: expandtab sw=4 ts=4 26 | -------------------------------------------------------------------------------- /moon/vehicles/test_rover.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from unittest.mock import MagicMock 3 | 4 | from moon.vehicles.rover import Rover 5 | 6 | 7 | JOINT_NAME = [b'bl_arm_joint', b'bl_steering_arm_joint', b'bl_wheel_joint', 8 | b'br_arm_joint', b'br_steering_arm_joint', b'br_wheel_joint', b'fl_arm_joint', 9 | b'fl_steering_arm_joint', b'fl_wheel_joint', b'fr_arm_joint', b'fr_steering_arm_joint', 10 | b'fr_wheel_joint', b'sensor_joint'] 11 | 12 | 13 | class RoverTest(unittest.TestCase): 14 | 15 | def test_rover_pid(self): 16 | rover = Rover(config={}, bus=MagicMock()) 17 | 18 | rover.joint_name = JOINT_NAME # in reality received as the first joint status 19 | rover.on_joint_effort([0]*len(JOINT_NAME)) 20 | 21 | def test_get_steering_and_effort(self): 22 | rover = Rover(config={}, bus=MagicMock()) 23 | self.assertEqual(rover.get_steering_and_effort(), ([0.0, 0.0, 0.0, 0.0], [0, 0, 0, 0])) 24 | 25 | rover.drive_speed = 500.0 # sigh, corresponds to 0.5m/s now 26 | self.assertEqual(rover.get_steering_and_effort(), ([0.0, 0.0, 0.0, 0.0], [40, 40, 40, 40])) 27 | 28 | rover.drive_speed = -500.0 29 | self.assertEqual(rover.get_steering_and_effort(), ([0.0, 0.0, 0.0, 0.0], [-40, -40, -40, -40])) 30 | 31 | # vim: expandtab sw=4 ts=4 32 | 33 | -------------------------------------------------------------------------------- /osgar/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from osgar.lib import create_load_tests 3 | load_tests = create_load_tests(__file__) 4 | -------------------------------------------------------------------------------- /osgar/drivers/opencv.py: -------------------------------------------------------------------------------- 1 | """ 2 | Log video stream provided by OpenCV camera 3 | """ 4 | 5 | import cv2 6 | from threading import Thread 7 | 8 | class LogOpenCVCamera: 9 | def __init__(self, config, bus): 10 | self.input_thread = Thread(target=self.run_input, daemon=True) 11 | self.bus = bus 12 | bus.register('raw') 13 | 14 | port = config.get('port', 0) 15 | self.cap = cv2.VideoCapture(port) 16 | self.sleep = config.get('sleep') 17 | 18 | def start(self): 19 | self.input_thread.start() 20 | 21 | def join(self, timeout=None): 22 | self.input_thread.join(timeout=timeout) 23 | 24 | def run_input(self): 25 | while self.bus.is_alive(): 26 | # Capture frame-by-frame 27 | ret, frame = self.cap.read() 28 | if ret: 29 | retval, data = cv2.imencode('*.jpeg', frame) 30 | if len(data) > 0: 31 | self.bus.publish('raw', data.tobytes()) 32 | if self.sleep is not None: 33 | self.bus.sleep(self.sleep) 34 | self.cap.release() 35 | 36 | def request_stop(self): 37 | self.bus.shutdown() 38 | 39 | # vim: expandtab sw=4 ts=4 40 | -------------------------------------------------------------------------------- /osgar/drivers/qorvo.py: -------------------------------------------------------------------------------- 1 | """ 2 | Simple(minded) driver for Qorvo UWB modules 3 | """ 4 | 5 | from osgar.node import Node 6 | 7 | 8 | class Qorvo(Node): 9 | def __init__(self, config, bus): 10 | super().__init__(config, bus) 11 | bus.register('range', 'raw') 12 | self.verbose = False 13 | self.initialized = False 14 | 15 | def on_raw(self, data): 16 | if not self.initialized: 17 | self.publish("raw", b'la\n') 18 | self.initialized = True 19 | 20 | def on_timer(self, data): 21 | if not self.initialized: 22 | self.publish("raw", b'\n') 23 | 24 | 25 | # vim: expandtab sw=4 ts=4 26 | -------------------------------------------------------------------------------- /osgar/drivers/resize.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | from osgar.node import Node 5 | 6 | class Resize(Node): 7 | def __init__(self, config, bus): 8 | super().__init__(config, bus) 9 | bus.register('image', 'depth') 10 | self.width = config['width'] 11 | self.height = config['height'] 12 | 13 | def on_depth(self, data): 14 | small_data = cv2.resize(data, (self.width, self.height)) 15 | self.publish('depth', small_data) 16 | 17 | def on_image(self, data): 18 | img = cv2.imdecode(np.frombuffer(data, np.uint8), cv2.IMREAD_ANYCOLOR) 19 | small_img = cv2.resize(img, (self.width, self.height)) 20 | small_data = cv2.imencode('.jpeg', small_img)[1].tobytes() 21 | self.publish('image', small_data) 22 | -------------------------------------------------------------------------------- /osgar/drivers/rtk_filter.py: -------------------------------------------------------------------------------- 1 | """ 2 | RTK filter (reduce GPS NMEA to 1Hz for query to server) 3 | """ 4 | from datetime import timedelta 5 | from osgar.node import Node 6 | 7 | 8 | class RTKFilter(Node): 9 | def __init__(self, config, bus): 10 | super().__init__(config, bus) 11 | bus.register('filtered') 12 | self.verbose = False 13 | self.trigger_time = None # not defined 14 | self.buf = b'' 15 | 16 | def on_nmea(self, data): 17 | if self.trigger_time is None: 18 | self.trigger_time = self.time + timedelta(seconds=1) 19 | self.buf = b'' 20 | return # skip first buffer 21 | if self.time < self.trigger_time: 22 | return # not there yet 23 | self.buf += data 24 | if b'$GNGGA' in self.buf: 25 | packet = self.buf[self.buf.index(b'$GNGGA'):] 26 | if b'\r\n' in packet: 27 | self.publish('filtered', packet[:packet.index(b'\r\n')+2]) 28 | self.trigger_time = self.time + timedelta(seconds=1) 29 | self.buf = b'' 30 | 31 | # vim: expandtab sw=4 ts=4 32 | -------------------------------------------------------------------------------- /osgar/drivers/test_logusb.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from array import array 3 | 4 | from osgar.lib.serialize import serialize, deserialize 5 | 6 | 7 | class LogUSBTest(unittest.TestCase): 8 | 9 | def test_array(self): 10 | # USB read returns array('B', [...]), which fails to serialize 11 | arr = array('B', [1, 2, 3]) 12 | b_arr = serialize(bytes(arr)) 13 | self.assertEqual(deserialize(b_arr), bytes([1, 2, 3])) 14 | 15 | # vim: expandtab sw=4 ts=4 16 | -------------------------------------------------------------------------------- /osgar/drivers/test_oak_camera.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from unittest.mock import MagicMock, patch 3 | from datetime import timedelta 4 | 5 | # depthai package is not necessarily available and it is not needed for this unittest 6 | with patch.dict('sys.modules', {'depthai': MagicMock()}): 7 | from osgar.drivers.oak_camera import OakCamera 8 | 9 | class OakCameraTest(unittest.TestCase): 10 | 11 | def test_usage(self): 12 | config = {} 13 | handler = MagicMock() 14 | cam = OakCamera(config, bus=handler) 15 | 16 | def test_nn_image_size(self): 17 | config = { 18 | 'nn_config': { 19 | 'input_size': '160x120' 20 | } 21 | } 22 | handler = MagicMock() 23 | cam = OakCamera(config, bus=handler) 24 | self.assertEqual(cam.oak_config_nn_image_size, (160, 120)) 25 | 26 | # vim: expandtab sw=4 ts=4 27 | -------------------------------------------------------------------------------- /osgar/drivers/test_spider.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from unittest.mock import MagicMock 3 | from datetime import timedelta 4 | 5 | from osgar.drivers.spider import Spider, CAN_triplet, sint8_diff 6 | from osgar.bus import Bus 7 | 8 | 9 | class SpiderTest(unittest.TestCase): 10 | 11 | def test_publish_status(self): 12 | logger=MagicMock() 13 | logger.write = MagicMock(return_value=timedelta(seconds=135)) 14 | bus = Bus(logger=logger) 15 | tester = bus.handle('tester') 16 | tester.register('can') 17 | spider = Spider(config={}, bus=bus.handle('spider')) 18 | bus.connect('tester.can', 'spider.can') 19 | bus.connect('spider.status', 'tester.status') 20 | 21 | tester.publish('can', CAN_triplet(0x200, [0, 0x80])) 22 | spider.start() 23 | dt, stream, data = tester.listen() 24 | spider.request_stop() 25 | spider.join() 26 | self.assertEqual(dt, timedelta(seconds=135)) 27 | self.assertEqual(stream, 'status') 28 | self.assertEqual(data, ([0x8000, None])) 29 | 30 | def test_8bit_diff(self): 31 | self.assertEqual(sint8_diff(0, 256), 0) 32 | self.assertEqual(sint8_diff(0, 1), -1) 33 | self.assertEqual(sint8_diff(255, 0), -1) 34 | 35 | 36 | # vim: expandtab sw=4 ts=4 37 | -------------------------------------------------------------------------------- /osgar/drivers/timer.py: -------------------------------------------------------------------------------- 1 | from threading import Thread 2 | import time 3 | 4 | 5 | class Timer: 6 | def __init__(self, config, bus): 7 | self.bus = bus 8 | bus.register('tick') 9 | self.sleep = config['sleep'] 10 | self.thread = Thread(target=self.run) 11 | self.time_zero = time.monotonic() 12 | 13 | def start(self): 14 | self.thread.start() 15 | 16 | def join(self, timeout=None): 17 | self.thread.join(timeout=timeout) 18 | 19 | def run(self): 20 | while self.bus.is_alive(): 21 | self.bus.publish('tick', time.monotonic() - self.time_zero) 22 | self.bus.sleep(self.sleep) 23 | 24 | def request_stop(self): 25 | self.bus.shutdown() 26 | -------------------------------------------------------------------------------- /osgar/lib/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def create_load_tests(filepath): 4 | from pathlib import Path 5 | start_dir = Path(filepath).parent 6 | def load_tests(loader, standard_tests, pattern): 7 | pattern = pattern or "test_*.py" 8 | package_tests = loader.discover(start_dir=start_dir, pattern=pattern) 9 | standard_tests.addTests(package_tests) 10 | return standard_tests 11 | return load_tests 12 | 13 | 14 | load_tests = create_load_tests(__file__) 15 | -------------------------------------------------------------------------------- /osgar/lib/mathex.py: -------------------------------------------------------------------------------- 1 | """ 2 | Extra math routines 3 | """ 4 | import math 5 | 6 | 7 | def normalizeAnglePIPI( angle ): 8 | while angle < -math.pi: 9 | angle += 2*math.pi 10 | while angle > math.pi: 11 | angle -= 2*math.pi 12 | return angle 13 | 14 | # vim: expandtab sw=4 ts=4 15 | -------------------------------------------------------------------------------- /osgar/lib/test_lidar_pts.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from osgar.lib.lidar_pts import equal_scans 4 | 5 | 6 | class LidarPtsTest(unittest.TestCase): 7 | 8 | def test_equal_scans(self): 9 | self.assertTrue(equal_scans([1, 2, 3], [1, 2, 3])) 10 | self.assertFalse(equal_scans([1, 2, 3], [1, 4, 3], tollerance=1)) 11 | 12 | 13 | # vim: expandtab sw=4 ts=4 14 | -------------------------------------------------------------------------------- /osgar/lib/test_unittest.py: -------------------------------------------------------------------------------- 1 | from .unittest import TestCase 2 | 3 | import numpy as np 4 | 5 | 6 | class Test(TestCase): 7 | 8 | def test_numpy(self): 9 | template = [1, 2, 3] 10 | a = np.asarray(template) 11 | b = np.asarray(template) 12 | self.assertEqual(a, b) 13 | self.assertNumpyEqual(a, b) 14 | 15 | with self.assertRaises(AssertionError): 16 | self.assertNumpyEqual(a, []) 17 | with self.assertRaises(AssertionError): 18 | self.assertNumpyEqual(a, template) 19 | 20 | def test_pose3d(self): 21 | a = [[0,0,0], [0,0,0,1]] 22 | with self.assertRaises(AssertionError): 23 | self.assertPose3dEqual([], []) 24 | 25 | self.assertPose3dEqual(a, a) 26 | 27 | def test_list(self): 28 | self.assertListAlmostEqual([1], [1]) 29 | self.assertListAlmostEqual([1, 2], [1, 2]) 30 | self.assertListAlmostEqual([1.1, 2], [1.1, 2]) 31 | self.assertListAlmostEqual([1.10000001, 2], [1.1, 2]) 32 | 33 | with self.assertRaises(AssertionError): 34 | self.assertListAlmostEqual([1.1000001, 2], [1.1, 2]) 35 | with self.assertRaises(AssertionError): 36 | self.assertListAlmostEqual([1, 2], [1, 3]) 37 | with self.assertRaises(AssertionError): 38 | self.assertListAlmostEqual([1, 2], [1, 2, 3]) 39 | -------------------------------------------------------------------------------- /osgar/node.py: -------------------------------------------------------------------------------- 1 | """ 2 | Node - processing unit 3 | """ 4 | from threading import Thread 5 | 6 | from osgar.bus import BusShutdownException 7 | 8 | 9 | class Node(Thread): 10 | """ 11 | Parent classs for all processing "nodes". 12 | """ 13 | def __init__(self, config, bus): 14 | super().__init__() 15 | self.setDaemon(True) 16 | self.bus = bus 17 | self.time = None 18 | 19 | def publish(self, channel, data): 20 | return self.bus.publish(channel, data) 21 | 22 | def listen(self): 23 | return self.bus.listen() 24 | 25 | def sleep(self, secs): 26 | self.bus.sleep(secs) 27 | 28 | def is_bus_alive(self): 29 | return self.bus.is_alive() 30 | 31 | def update(self): 32 | timestamp, channel, data = self.bus.listen() 33 | self.time = timestamp 34 | handler = getattr(self, "on_" + channel, None) 35 | if handler is not None: 36 | handler(data) 37 | else: 38 | assert False, channel # unknown 39 | return channel 40 | 41 | def run(self): 42 | try: 43 | while True: 44 | self.update() 45 | except BusShutdownException: 46 | pass 47 | 48 | def request_stop(self): 49 | self.bus.shutdown() 50 | 51 | # vim: expandtab sw=4 ts=4 52 | -------------------------------------------------------------------------------- /osgar/obstdet3d.py: -------------------------------------------------------------------------------- 1 | """ 2 | Obstacle Detection 3D 3 | """ 4 | import numpy as np 5 | 6 | from osgar.node import Node 7 | 8 | 9 | class ObstacleDetector3D(Node): 10 | def __init__(self, config, bus): 11 | super().__init__(config, bus) 12 | bus.register('obstacle') 13 | 14 | def on_depth(self, data): 15 | assert data.shape == (400, 640), data.shape 16 | selection = data[150:250, 300:340] 17 | mask = selection > 0 # not valid data? 18 | if mask.max() == True: 19 | dist = selection[mask].min() / 1000 20 | else: 21 | dist = 0.0 22 | self.publish('obstacle', float(dist)) 23 | # print(self.time, dist) 24 | 25 | # vim: expandtab sw=4 ts=4 26 | -------------------------------------------------------------------------------- /osgar/platforms/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def create_load_tests(filepath): 4 | from pathlib import Path 5 | start_dir = Path(filepath).parent 6 | def load_tests(loader, standard_tests, pattern): 7 | pattern = pattern or "test_*.py" 8 | package_tests = loader.discover(start_dir=start_dir, pattern=pattern) 9 | standard_tests.addTests(package_tests) 10 | return standard_tests 11 | return load_tests 12 | 13 | 14 | load_tests = create_load_tests(__file__) 15 | -------------------------------------------------------------------------------- /osgar/platforms/test_yuhesen.py: -------------------------------------------------------------------------------- 1 | 2 | import unittest 3 | from unittest.mock import MagicMock 4 | from datetime import timedelta 5 | 6 | from osgar.platforms.yuhesen import FR07 7 | 8 | 9 | class FR07Test(unittest.TestCase): 10 | 11 | def test_usage(self): 12 | bus = MagicMock() 13 | robot = FR07(bus=bus, config={}) 14 | robot.on_can([0x18c4eaef, bytes.fromhex('3200000000704002'), 1]) 15 | bus.publish.assert_called_with('emergency_stop', True) 16 | 17 | def test_control_speed(self): 18 | bus = MagicMock() 19 | robot = FR07(bus=bus, config={}) 20 | robot.desired_speed = 5.0 # m/s (from user manual) 21 | robot.on_can([0x18c4d2ef, bytes.fromhex('0100700000102041'), 1]) 22 | bus.publish.assert_called_with('can', [0x18C4D2D0, bytes.fromhex('843801000000209d'), 1]) 23 | 24 | robot.on_can([0x18c4d2ef, bytes.fromhex('843801000000209d'), 1]) 25 | self.assertEqual(robot.last_speed, 5000) 26 | 27 | def test_control_steering(self): 28 | bus = MagicMock() 29 | robot = FR07(bus=bus, config={}) 30 | robot.desired_steering_angle_deg = -25.0 # deg (from user manual) 31 | robot.on_can([0x18c4d2ef, bytes.fromhex('0100700000102041'), 1]) 32 | bus.publish.assert_called_with('can', [0x18C4D2D0, bytes.fromhex('0400c0630f002088'), 1]) 33 | 34 | robot.on_can([0x18c4d2ef, bytes.fromhex('0400c0630f002088'), 1]) 35 | self.assertEqual(robot.last_steering, -2500) 36 | -------------------------------------------------------------------------------- /osgar/test_followme.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from unittest.mock import MagicMock 3 | 4 | from osgar.followme import FollowMe, EmergencyStopException 5 | from osgar.bus import Bus 6 | 7 | 8 | class FollowMeTest(unittest.TestCase): 9 | 10 | def test_usage(self): 11 | bus = Bus(MagicMock()) 12 | app = FollowMe(config={}, bus=bus.handle('app')) 13 | tester = bus.handle('tester') 14 | tester.register('emergency_stop') 15 | bus.connect('tester.emergency_stop', 'app.emergency_stop') 16 | tester.publish('emergency_stop', True) 17 | 18 | app.raise_exception_on_stop = True 19 | 20 | with self.assertRaises(EmergencyStopException): 21 | app.followme() 22 | 23 | # vim: expandtab sw=4 ts=4 24 | -------------------------------------------------------------------------------- /osgar/test_go.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from unittest.mock import MagicMock 3 | 4 | from osgar.go import Go 5 | 6 | 7 | class GoTest(unittest.TestCase): 8 | 9 | def test_usage(self): 10 | bus = MagicMock() 11 | app = Go(bus=bus, config={ 12 | # required parameters 13 | 'max_speed': 0.5, 14 | 'dist': 1.0, 15 | 'timeout': 10 16 | }) 17 | app.on_pose2d([0, 0, 0]) 18 | # bus.publish.assert_called_with('emergency_stop', True) 19 | -------------------------------------------------------------------------------- /osgar/tools/README.md: -------------------------------------------------------------------------------- 1 | OSGAR TOOLS 2 | =========== 3 | 4 | Tools for OSGAR (Open Source Garden/Generic Autonomous Robot) 5 | 6 | 7 | This package contains tools used for post-processing and analysis of 8 | logfiles. 9 | -------------------------------------------------------------------------------- /osgar/tools/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotika/osgar/ab10ba4004329dcc0ea1ffc68ac2334bb1995c38/osgar/tools/__init__.py -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.black] 2 | line-length = 120 3 | skip-string-normalization = true 4 | 5 | [tool.isort] 6 | # A Black (https://github.com/psf/black)-compatible isort 7 | # (https://timothycrosley.github.io/isort/) config. Copy-pasted from Black's 8 | # README. 9 | multi_line_output = 3 10 | include_trailing_comma = true 11 | force_grid_wrap = 0 12 | use_parentheses = true 13 | line_length = 120 14 | -------------------------------------------------------------------------------- /release.bat: -------------------------------------------------------------------------------- 1 | python setup.py sdist bdist_wheel 2 | python -m twine upload --repository-url https://test.pypi.org/legacy/ dist/* 3 | REM python -m twine upload --repository-url https://upload.pypi.org/legacy/ dist/* 4 | 5 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pyserial==3.5 2 | msgpack==1.0.5 3 | pyusb==1.2.1 4 | opencv-python==4.7.0.72 5 | requests==2.28.2 6 | pyzmq==25.0.2 7 | pyrealsense2==2.53.1.4623 8 | numpy==1.22.0 9 | protobuf==3.20.0 10 | Shapely==2.0.1 11 | -------------------------------------------------------------------------------- /subt/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from osgar.lib import create_load_tests 4 | load_tests = create_load_tests(__file__) 5 | -------------------------------------------------------------------------------- /subt/__main__.py: -------------------------------------------------------------------------------- 1 | from .main import main 2 | main() 3 | 4 | -------------------------------------------------------------------------------- /subt/artf_gas.py: -------------------------------------------------------------------------------- 1 | """ 2 | OSGAR Gas detector 3 | """ 4 | # This is the simplest version taken from subt/artifacts.py - i.e. use reference position as 5 | # the first moment when the robot detects gas. More advanced/precise implementations can take the map 6 | # or scan and report the entering doors as defined in the rules. 7 | 8 | from osgar.node import Node 9 | from subt.artifacts import GAS 10 | 11 | 12 | class ArtifactGasDetector(Node): 13 | def __init__(self, config, bus): 14 | super().__init__(config, bus) 15 | bus.register("localized_artf") 16 | self.xyz = None 17 | self.last_bottom_scan = 0.0 # expected to never arrive for ground robots 18 | 19 | def on_gas_detected(self, data): 20 | if data and self.xyz is not None: 21 | x, y, z = self.xyz 22 | self.publish('localized_artf', [GAS, [x, y, z - self.last_bottom_scan]]) 23 | 24 | def on_pose3d(self, data): 25 | self.xyz = data[0] # ignore orientation 26 | 27 | def on_bottom_scan(self, data): 28 | self.last_bottom_scan = data[0] 29 | 30 | # vim: expandtab sw=4 ts=4 31 | -------------------------------------------------------------------------------- /subt/artf_utils.py: -------------------------------------------------------------------------------- 1 | EXTINGUISHER = 'TYPE_EXTINGUISHER' 2 | BACKPACK = 'TYPE_BACKPACK' 3 | PHONE = 'TYPE_PHONE' 4 | DRILL = 'TYPE_DRILL' 5 | RESCUE_RANDY = 'TYPE_RESCUE_RANDY' 6 | VENT = 'TYPE_VENT' 7 | GAS = 'TYPE_GAS' 8 | HELMET = 'TYPE_HELMET' 9 | ROPE = 'TYPE_ROPE' 10 | CUBE = 'TYPE_CUBE' 11 | 12 | 13 | NAME2IGN = { 14 | 'survivor': RESCUE_RANDY, 15 | 'backpack': BACKPACK, 16 | 'phone': PHONE, 17 | 'helmet': HELMET, 18 | 'rope': ROPE, 19 | 'fire_extinguisher': EXTINGUISHER, 20 | 'drill': DRILL, 21 | 'vent': VENT, 22 | 'cube' : CUBE 23 | } 24 | -------------------------------------------------------------------------------- /subt/aws2info.py: -------------------------------------------------------------------------------- 1 | """ 2 | Extract position with topics statistic from AWS ROS_INFO output 3 | """ 4 | 5 | 6 | def aws2info(filename, outname): 7 | KEY = 'Python3: stdout ' 8 | with open(filename) as f, open(outname, 'w') as out: 9 | for line in f: 10 | if KEY in line and line.strip().endswith(']'): 11 | out.write(line[line.index(KEY)+len(KEY):]) 12 | 13 | 14 | if __name__ == '__main__': 15 | import argparse 16 | 17 | parser = argparse.ArgumentParser(description=__doc__) 18 | parser.add_argument('filename', help='AWS ROS recorded log file') 19 | args = parser.parse_args() 20 | 21 | assert 'rosout.log' in args.filename, args.filename 22 | outname = args.filename.replace('rosout.log', 'info.txt') 23 | aws2info(args.filename, outname=outname) 24 | 25 | # vim: expandtab sw=4 ts=4 26 | -------------------------------------------------------------------------------- /subt/check_gas.py: -------------------------------------------------------------------------------- 1 | from osgar.logger import LogReader, lookup_stream_id 2 | from osgar.lib.serialize import deserialize 3 | 4 | 5 | if __name__ == "__main__": 6 | import argparse 7 | 8 | parser = argparse.ArgumentParser(description='Parse logged detected_gas and extract "Gas" artifact') 9 | parser.add_argument('logfile', help='recorded log file') 10 | args = parser.parse_args() 11 | 12 | only_stream = lookup_stream_id(args.logfile, 'gas_detector.co2') 13 | best = None 14 | with LogReader(args.logfile, only_stream_id=only_stream) as log: 15 | for timestamp, stream_id, data in log: 16 | co2 = deserialize(data) 17 | if best is None or co2 > best[1]: 18 | print(timestamp, co2) 19 | best = timestamp, co2 20 | print('--------------------') 21 | if best is not None: 22 | print('best:', best[0], best[1]) 23 | else: 24 | print("No Gas, sorry") 25 | 26 | # vim: expandtab sw=4 ts=4 27 | 28 | -------------------------------------------------------------------------------- /subt/check_phone.py: -------------------------------------------------------------------------------- 1 | from osgar.logger import LogReader, lookup_stream_id 2 | from osgar.lib.serialize import deserialize 3 | 4 | CELL_PREFIX = "PhoneArtifact" 5 | 6 | if __name__ == "__main__": 7 | import argparse 8 | 9 | parser = argparse.ArgumentParser(description='Parse logged WiFi AP scans and extract "Cell Phone" artifact') 10 | parser.add_argument('logfile', help='recorded log file') 11 | args = parser.parse_args() 12 | 13 | only_stream = lookup_stream_id(args.logfile, 'wifi.wifiscan') 14 | best = None 15 | with LogReader(args.logfile, only_stream_id=only_stream) as log: 16 | for timestamp, stream_id, data in log: 17 | wifi_list = deserialize(data) 18 | for name, signal in wifi_list: 19 | if name.startswith(CELL_PREFIX): 20 | print(timestamp, name, signal) 21 | if best is None or signal > best[2]: 22 | best = timestamp, name, signal 23 | print('--------------------') 24 | if best is not None: 25 | print('best:', best[0], best[1], best[2]) 26 | else: 27 | print("No Cell Phone, sorry") 28 | 29 | # vim: expandtab sw=4 ts=4 30 | 31 | -------------------------------------------------------------------------------- /subt/config/darpa-artf.csv: -------------------------------------------------------------------------------- 1 | artf, x, y, z 2 | Backpack, 2, -21.2, 0.5 3 | Cell Phone, 5, 5, 5 4 | -------------------------------------------------------------------------------- /subt/docker/base/tags: -------------------------------------------------------------------------------- 1 | robotika/subt-base 2 | -------------------------------------------------------------------------------- /subt/docker/cudatest/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM robotika/subt-base:2020-05-06 2 | 3 | ADD subt/docker/cudatest/cudatest_entrypoint.bash src/ 4 | ADD subt/docker/cudatest/cudatest3.py src/ 5 | ADD subt/docker/cudatest/cloudsim_run.py src/ 6 | 7 | ENTRYPOINT [ "./src/cudatest_entrypoint.bash" ] 8 | 9 | CMD [ "./src/cloudsim_run.py", "/osgar-ws/env/bin/python", "src/cudatest3.py" ] 10 | -------------------------------------------------------------------------------- /subt/docker/cudatest/cudatest3.py: -------------------------------------------------------------------------------- 1 | 2 | import torch 3 | 4 | if torch.cuda.is_available(): 5 | print("torch ok") 6 | else: 7 | print("torch failed") 8 | 9 | import tensorflow as tf 10 | 11 | if len(tf.config.list_physical_devices('GPU')) >= 1: 12 | print("tf ok") 13 | else: 14 | print("tf failed") 15 | -------------------------------------------------------------------------------- /subt/docker/cudatest/cudatest_entrypoint.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # We need to look for NVidia libraries, but they are not around yet when 4 | # building the image, so `ldconfig` in Dockerfile is not a working solution. 5 | # https://gitlab.com/nvidia/container-images/cuda/-/issues/34 6 | sudo ldconfig 7 | 8 | echo "source /opt/ros/melodic/setup.sh" >> ~/.bashrc 9 | 10 | source /opt/ros/melodic/setup.bash 11 | 12 | exec "$@" 13 | -------------------------------------------------------------------------------- /subt/docker/gui/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM osrf/subt-virtual-testbed:cloudsim_sim_latest 2 | 3 | RUN mkdir -p /home/developer/.ignition/gazebo/ 4 | 5 | RUN cd /home/developer/.ignition/fuel/fuel.ignitionrobotics.org/OpenRobotics/models/ && \ 6 | ln -s Robotika_Freyja_Sensor_Config_2 ROBOTIKA_FREYJA_SENSOR_CONFIG_2 7 | 8 | COPY ./subt/docker/gui/entrypoint.bash . 9 | 10 | ENTRYPOINT ["./entrypoint.bash"] 11 | 12 | ENV IGN_PARTITION=sim 13 | 14 | CMD ["ign", "gazebo", "-g"] 15 | -------------------------------------------------------------------------------- /subt/docker/gui/entrypoint.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # We need to look for NVidia libraries, but they are not around yet when 4 | # building the image, so `ldconfig` in Dockerfile is not a working solution. 5 | # https://gitlab.com/nvidia/container-images/cuda/-/issues/34 6 | sudo ldconfig 7 | 8 | exec "$@" 9 | -------------------------------------------------------------------------------- /subt/docker/loadtest/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM osrf/subt-virtual-testbed:subt_solution_latest 2 | 3 | RUN sudo apt-get update && sudo apt-get install -y \ 4 | python-bcrypt \ 5 | python-pip \ 6 | python-pip-whl \ 7 | python-virtualenv \ 8 | && sudo rm -rf /var/lib/apt/lists/* 9 | 10 | COPY subt/docker/loadtest/main.py subt/docker/loadtest/loadtest_entrypoint.bash ./ 11 | 12 | ENTRYPOINT ["./loadtest_entrypoint.bash"] 13 | 14 | CMD ["python", "main.py", "100"] 15 | -------------------------------------------------------------------------------- /subt/docker/loadtest/loadtest_entrypoint.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source /opt/ros/melodic/setup.bash 4 | source ~/subt_solution/install/setup.sh 5 | 6 | exec "$@" 7 | -------------------------------------------------------------------------------- /subt/docker/robotika/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | cd build && $(MAKE) --no-print-directory 3 | -------------------------------------------------------------------------------- /subt/docker/robotika/entrypoint.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source /osgar-ws/devel/setup.sh 4 | 5 | # We need to look for NVidia libraries, but they are not around yet when 6 | # building the image, so `ldconfig` in Dockerfile is not a working solution. 7 | # https://gitlab.com/nvidia/container-images/cuda/-/issues/34 8 | sudo ldconfig 9 | 10 | exec "$@" 11 | -------------------------------------------------------------------------------- /subt/docker/robotika/python_logging.conf: -------------------------------------------------------------------------------- 1 | [loggers] 2 | keys=root, rosout 3 | 4 | [handlers] 5 | keys=fileHandler,streamHandler 6 | 7 | [formatters] 8 | keys=defaultFormatter 9 | 10 | [logger_root] 11 | level=DEBUG 12 | handlers=fileHandler 13 | 14 | [logger_rosout] 15 | level=DEBUG 16 | handlers=streamHandler 17 | propagate=1 18 | qualname=rosout 19 | 20 | [handler_fileHandler] 21 | class=handlers.RotatingFileHandler 22 | level=DEBUG 23 | formatter=defaultFormatter 24 | # log filename, mode, maxBytes, backupCount 25 | args=(os.environ['ROS_LOG_FILENAME'],'a', 50000000, 4) 26 | 27 | [handler_streamHandler] 28 | class=rosgraph.roslogging.RosStreamHandler 29 | level=DEBUG 30 | formatter=defaultFormatter 31 | # colorize output flag 32 | args=(True,) 33 | 34 | [formatter_defaultFormatter] 35 | format=[%(name)s][%(levelname)s] %(asctime)s: %(message)s 36 | -------------------------------------------------------------------------------- /subt/docker/robotika/rosconsole.config: -------------------------------------------------------------------------------- 1 | # 2 | # rosconsole will find this file by default at $ROS_ROOT/config/rosconsole.config 3 | # 4 | # You can define your own by e.g. copying this file and setting 5 | # ROSCONSOLE_CONFIG_FILE (in your environment) to point to the new file 6 | # 7 | log4j.logger.ros.roscpp=DEBUG 8 | log4j.logger.ros.roscpp.superdebug=WARN 9 | 10 | # hide messages about recursive call 11 | log4j.logger.ros.roscpp.cached_parameters=INFO 12 | 13 | # hide messages about connections 14 | log4j.logger.ros.roscpp.roscpp_internal=INFO 15 | -------------------------------------------------------------------------------- /subt/docker/unittest/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM osrf/subt-virtual-testbed:subt_solution_latest 2 | 3 | COPY subt/docker/unittest/run_solution.bash ./ 4 | 5 | COPY subt/docker/unittest/subt_seed_node.cc ./src/subt_seed/src/subt_seed_node.cc 6 | RUN /bin/bash -c 'source /opt/ros/melodic/setup.bash && catkin_make install' 7 | 8 | ENTRYPOINT ["./run_solution.bash"] 9 | 10 | -------------------------------------------------------------------------------- /subt/docker/unittest/run_solution.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | . /opt/ros/melodic/setup.bash 4 | . ~/subt_solution/install/setup.sh 5 | 6 | # Run your solution and wait for ROS master 7 | # http://wiki.ros.org/roslaunch/Commandline%20Tools#line-45 8 | roslaunch subt_seed x1.launch --wait 9 | -------------------------------------------------------------------------------- /subt/gazebo_poses.py: -------------------------------------------------------------------------------- 1 | from xml.sax.handler import ContentHandler 2 | from xml.sax import make_parser 3 | 4 | import base64 5 | import zlib 6 | 7 | 8 | class GazeboHandler(ContentHandler): 9 | def __init__(self): 10 | super().__init__() 11 | self.active = False 12 | self.index = 0 13 | 14 | def startElement(self, name, attrs): 15 | assert name in ['gazebo_log', 'header', 'log_version', 'gazebo_version', 16 | 'rand_seed', 'chunk', 'log_start', 'log_end'], name 17 | 18 | if name == 'chunk': 19 | assert attrs['encoding'] == 'zlib', attrs['encoding'] 20 | self.data = '' 21 | self.active = (name == 'chunk') 22 | 23 | def characters(self, data): 24 | if self.active: 25 | self.data += data 26 | 27 | def endElement(self, name): 28 | if name == 'chunk': 29 | subtree = zlib.decompress(base64.b64decode(self.data)) 30 | if self.index == 100: 31 | print(subtree.decode('ascii')) 32 | self.index += 1 33 | 34 | 35 | if __name__ == "__main__": 36 | import sys 37 | handler = GazeboHandler() 38 | 39 | saxparser = make_parser() 40 | saxparser.setContentHandler(handler) 41 | 42 | with open(sys.argv[1]) as f: 43 | saxparser.parse(f) 44 | 45 | 46 | # vim: expandtab sw=4 ts=4 47 | -------------------------------------------------------------------------------- /subt/ign.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | message Time { 4 | int64 sec = 1; 5 | int32 nsec = 2; 6 | } 7 | 8 | message Header { 9 | message Map { 10 | string key = 1; 11 | repeated string value = 2; 12 | } 13 | Time stamp = 1; 14 | repeated Map data = 2; 15 | } 16 | 17 | message Vector3d { 18 | Header header = 1; 19 | double x = 2; 20 | double y = 3; 21 | double z = 4; 22 | } 23 | 24 | message Quaternion { 25 | Header header = 1; 26 | double x = 2; 27 | double y = 3; 28 | double z = 4; 29 | double w = 5; 30 | } 31 | 32 | message Pose { 33 | Header header = 1; 34 | string name = 2; 35 | uint32 id = 3; 36 | Vector3d position = 4; 37 | Quaternion orientation = 5; 38 | } 39 | 40 | message Pose_V { 41 | Header header = 1; 42 | repeated Pose pose = 2; 43 | } 44 | 45 | message Artifact 46 | { 47 | uint32 type = 1; 48 | Pose pose = 2; 49 | } 50 | 51 | message ArtifactScore 52 | { 53 | uint32 report_id = 1; 54 | Artifact artifact = 2; 55 | Time submitted_datetime = 3; 56 | Time sim_time = 4; 57 | uint32 run = 5; 58 | string report_status = 6; 59 | int32 score_change = 7; 60 | } 61 | 62 | message StringMsg 63 | { 64 | Header header = 1; 65 | string data = 2; 66 | } 67 | -------------------------------------------------------------------------------- /subt/mytimer.py: -------------------------------------------------------------------------------- 1 | """ 2 | Timer 3 | """ 4 | from threading import Thread 5 | 6 | from osgar.bus import BusShutdownException 7 | 8 | 9 | class MyTimer(Thread): 10 | def __init__(self, config, bus): 11 | Thread.__init__(self) 12 | self.setDaemon(True) 13 | self.bus = bus 14 | self.sleep_time = config['sleep'] 15 | 16 | def run(self): 17 | try: 18 | while self.bus.is_alive(): 19 | self.bus.publish('tick', None) 20 | self.bus.sleep(self.sleep_time) 21 | 22 | except BusShutdownException: 23 | pass 24 | 25 | def request_stop(self): 26 | self.bus.shutdown() 27 | 28 | # vim: expandtab sw=4 ts=4 29 | 30 | -------------------------------------------------------------------------------- /subt/octomap.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "fromrospy": { 6 | "driver": "osgar.drivers.pull:Pull", 7 | "init": { 8 | "outputs": ["rot", "acc", "orientation", "battery_state", "score", "pose3d", 9 | "image_front", "image_rear", "scan_front", "scan_rear", "depth_front:null", "depth_rear:null", 10 | "octomap:gz"] 11 | } 12 | }, 13 | "octomap": { 14 | "driver": "subt.octomap:Octomap" 15 | } 16 | }, 17 | "links": [["fromrospy.octomap", "octomap.octomap"] 18 | ] 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /subt/points2scan.py: -------------------------------------------------------------------------------- 1 | """ 2 | Convert 3D points to "lidar" scan 3 | """ 4 | import math 5 | 6 | import cv2 7 | import numpy as np 8 | 9 | from osgar.node import Node 10 | from osgar.bus import BusShutdownException 11 | 12 | 13 | class PointsToScan(Node): 14 | def __init__(self, config, bus): 15 | super().__init__(config, bus) 16 | bus.register("scan360") 17 | self.debug_arr = [] 18 | 19 | def on_points(self, data): 20 | assert data.shape == (16, 1800, 3), data.shape 21 | self.debug_arr = data 22 | index = (np.arange(360) * (1800/360)).astype(int) 23 | xyz = data[8][index] # mid index for 16 lidars 24 | X, Y, Z = xyz[:, 0], xyz[:, 1], xyz[:, 2] 25 | dist_i = (np.hypot(X, Y) * 1000).astype(int) 26 | mask = dist_i < 400 27 | dist_i[mask] = 0 28 | self.publish('scan360', dist_i.tolist()) 29 | 30 | def draw(self): 31 | import matplotlib.pyplot as plt 32 | 33 | data = self.debug_arr.reshape(16 * 1000, 3) 34 | for z_min, z_max, color in [(-100, -0.5, 'gray'), (1, 100, 'blue'), (-0.5, 1, 'red')]: 35 | arr_x = [x for x, y, z in data if z_min < z < z_max] 36 | arr_y = [y for x, y, z in data if z_min < z < z_max] 37 | plt.plot(arr_x, arr_y, 'o', linewidth=2, color=color) 38 | 39 | plt.axes().set_aspect('equal', 'datalim') 40 | plt.legend() 41 | plt.show() 42 | 43 | # vim: expandtab sw=4 ts=4 44 | -------------------------------------------------------------------------------- /subt/ros/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from osgar.lib import create_load_tests 4 | load_tests = create_load_tests(__file__) 5 | -------------------------------------------------------------------------------- /subt/ros/base/__init__.py: -------------------------------------------------------------------------------- 1 | #python package 2 | 3 | -------------------------------------------------------------------------------- /subt/ros/base/custom_rosconsole.conf: -------------------------------------------------------------------------------- 1 | # Set the default ros output to warning and higher 2 | log4j.logger.ros=DEBUG 3 | -------------------------------------------------------------------------------- /subt/ros/base/launch/base.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /subt/ros/base/src/__init__.py: -------------------------------------------------------------------------------- 1 | #python package 2 | 3 | -------------------------------------------------------------------------------- /subt/ros/base/src/base_transform.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | from __future__ import print_function 4 | import rospy 5 | from nav_msgs.msg import Odometry 6 | import tf 7 | import pdb 8 | 9 | 10 | def on_new_odom_callback(odom): 11 | pose = odom.pose.pose.position 12 | orientation = odom.pose.pose.orientation 13 | broadcasterOdom.sendTransform( 14 | (pose.x,pose.y,pose.z), 15 | (orientation.x,orientation.y,orientation.z,orientation.w), 16 | rospy.Time.now(), 17 | "base_link", 18 | "odom" 19 | ) 20 | 21 | 22 | 23 | rospy.init_node("base_transform",log_level=rospy.DEBUG) 24 | lastTime = rospy.Time.now() 25 | subscriberOdom = rospy.Subscriber("/odom", Odometry, on_new_odom_callback, queue_size=15) 26 | broadcasterOdom = tf.TransformBroadcaster() 27 | 28 | 29 | r = rospy.spin() 30 | 31 | 32 | -------------------------------------------------------------------------------- /subt/ros/base/src/compass.py: -------------------------------------------------------------------------------- 1 | import math 2 | import pdb 3 | import serial 4 | import time 5 | import os 6 | 7 | 8 | 9 | class Compass(): 10 | def __init__(self): 11 | self.port = serial.Serial("/dev/ttyUSB0",baudrate=19200,timeout=5) 12 | self.lastCompass = -1 13 | 14 | def update(self): 15 | 16 | self.port.write(b"\x55\xC1\x02\x02") 17 | data1 = self.port.read() 18 | data2 = self.port.read() 19 | value = ord(data1) * 256 + ord(data2) 20 | self.lastCompass = value 21 | return value 22 | -------------------------------------------------------------------------------- /subt/ros/proxy/launch/sim.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /subt/ros/proxy/launch/teambase.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /subt/ros/proxy/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | proxy 4 | 0.0.0 5 | Proxies between osgar and ros 6 | 7 | zbynek 8 | 9 | MIT 10 | 11 | catkin 12 | 13 | rospy 14 | roscpp 15 | subt_communication_broker 16 | subt_ign 17 | 18 | std_msgs 19 | subt_msgs 20 | geometry_msgs 21 | rosgraph_msgs 22 | sensor_msgs 23 | nav_msgs 24 | std_srvs 25 | 26 | cv_bridge 27 | tf 28 | 29 | 30 | -------------------------------------------------------------------------------- /subt/ros/robot/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from osgar.lib import create_load_tests 4 | load_tests = create_load_tests(__file__) 5 | -------------------------------------------------------------------------------- /subt/ros/robot/custom_rosconsole.conf: -------------------------------------------------------------------------------- 1 | # Set the default ros output to warning and higher 2 | log4j.logger.ros=FATAL 3 | # Override my package to output everything 4 | #log4j.logger.ros.move_base=DEBUG 5 | -------------------------------------------------------------------------------- /subt/ros/robot/launch/straight.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /subt/ros/robot/params_car/camera_calibration.yaml: -------------------------------------------------------------------------------- 1 | image_width: 640 2 | image_height: 480 3 | camera_name: narrow_stereo 4 | camera_matrix: 5 | rows: 3 6 | cols: 3 7 | data: [447.464054, 0.000000, 330.673909, 0.000000, 453.975988, 254.771887, 0.000000, 0.000000, 1.000000] 8 | distortion_model: plumb_bob 9 | distortion_coefficients: 10 | rows: 1 11 | cols: 5 12 | data: [-0.336467, 0.116057, -0.001453, -0.001215, 0.000000] 13 | rectification_matrix: 14 | rows: 3 15 | cols: 3 16 | data: [1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000] 17 | projection_matrix: 18 | rows: 3 19 | cols: 4 20 | data: [361.502411, 0.000000, 333.397355, 0.000000, 0.000000, 406.817780, 257.541316, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000] 21 | -------------------------------------------------------------------------------- /subt/ros/robot/params_car/costmap_common_params.yaml: -------------------------------------------------------------------------------- 1 | obstacle_range: 2.5 2 | raytrace_range: 3.0 3 | footprint: [[ 0.4, 0.35], [-0.4, 0.35], [-0.4, -0.35], [ 0.4, -0.35]] 4 | #footprint_padding: 0.05 5 | footprint_padding: 0.01 6 | #footprint: [[ 0, 0], [-0, 0], [-0, -0], [ 0, -0]] 7 | 8 | #robot_radius: ir_of_robot 9 | transform_tolerance: 1 10 | 11 | controller_patience: 2.0 12 | 13 | recovery_behaviors: [ 14 | {name: conservative_clear, type: clear_costmap_recovery/ClearCostmapRecovery}, 15 | {name: aggressive_clear, type: clear_costmap_recovery/ClearCostmapRecovery} 16 | ] 17 | 18 | conservative_clear: 19 | reset_distance: 3.00 20 | aggressive_clear: 21 | reset_distance: 1.84 22 | 23 | -------------------------------------------------------------------------------- /subt/ros/robot/params_car/ekf_params.yaml: -------------------------------------------------------------------------------- 1 | ekf_se_map: 2 | frequency: 10 3 | sensor_timeout: 0.1 4 | two_d_mode: true 5 | transform_time_offset: 0.2 6 | transform_timeout: 0.0 7 | print_diagnostics: true 8 | debug: false 9 | 10 | map_frame: map 11 | odom_frame: odom 12 | base_link_frame: base_link 13 | world_frame: map 14 | 15 | # ------------------------------------- 16 | # Wheel odometry: 17 | odom0: /odom 18 | # 19 | odom0_config: [false, false, false, 20 | false, false, false, 21 | true, true, false, 22 | false, false, true, 23 | false, false, false] 24 | odom0_queue_size: 10 25 | odom0_nodelay: true 26 | odom0_differential: false 27 | odom0_relative: false 28 | # ------------------------------------- 29 | # GPS odometry: 30 | odom1: /odometry/gps 31 | odom1_config: [true, true, false, 32 | false, false, false, 33 | false, false, false, 34 | false, false, false, 35 | false, false, false] 36 | odom1_queue_size: 10 37 | odom1_nodelay: true 38 | odom1_differential: false 39 | odom1_relative: false 40 | -------------------------------------------------------------------------------- /subt/ros/robot/params_car/global_costmap_params.yaml: -------------------------------------------------------------------------------- 1 | global_costmap: 2 | plugins: 3 | - {name: static, type: "costmap_2d::StaticLayer"} 4 | - {name: inflation, type: "costmap_2d::InflationLayer"} 5 | 6 | robot_base_frame: base_link 7 | global_frame: map 8 | update_frequency: 10.0 9 | publish_frequency: 10.0 10 | static_map: true 11 | resolution: 0.1 12 | 13 | # inflation: 14 | inflation_radius: 0.5 15 | 16 | 17 | -------------------------------------------------------------------------------- /subt/ros/robot/params_car/local_costmap_params.yaml: -------------------------------------------------------------------------------- 1 | local_costmap: 2 | plugins: 3 | - {name: obstacles, type: "costmap_2d::ObstacleLayer"} 4 | # assuming receiving a cloud from rtabmap_ros/obstacles_detection node 5 | 6 | global_frame: odom 7 | robot_base_frame: base_link 8 | update_frequency: 10.0 9 | publish_frequency: 10.0 10 | static_map: false 11 | rolling_window: true 12 | width: 10.0 13 | height: 10.0 14 | resolution: 0.1 15 | origin_x: -5.0 16 | origin_y: -5.0 17 | track_unknown_space: false 18 | obstacles: 19 | publish_voxel_map: true 20 | observation_sources: laser_scan_sensor 21 | 22 | laser_scan_sensor: { 23 | sensor_frame: laser_mount_link, 24 | data_type: LaserScan, 25 | topic: "scan_horizontal", 26 | expected_update_rate: 0.5, 27 | marking: true, 28 | clearing: true, 29 | inf_is_valid: true, 30 | min_obstacle_height: -99999.0, 31 | max_obstacle_height: 99999.0} 32 | -------------------------------------------------------------------------------- /subt/ros/robot/params_car/navsat_params.yaml: -------------------------------------------------------------------------------- 1 | navsat_transform: 2 | frequency: 30 3 | delay: 3.0 4 | magnetic_declination_radians: 0.0 5 | yaw_offset: 0 6 | zero_altitude: true 7 | broadcast_utm_transform: false 8 | publish_filtered_gps: true 9 | use_odometry_yaw: false 10 | wait_for_datum: false 11 | broadcast_utm_transform_as_parent_frame: false 12 | -------------------------------------------------------------------------------- /subt/ros/robot/params_common/camera_calibration.yaml: -------------------------------------------------------------------------------- 1 | image_width: 640 2 | image_height: 480 3 | camera_name: narrow_stereo 4 | camera_matrix: 5 | rows: 3 6 | cols: 3 7 | data: [447.464054, 0.000000, 330.673909, 0.000000, 453.975988, 254.771887, 0.000000, 0.000000, 1.000000] 8 | distortion_model: plumb_bob 9 | distortion_coefficients: 10 | rows: 1 11 | cols: 5 12 | data: [-0.336467, 0.116057, -0.001453, -0.001215, 0.000000] 13 | rectification_matrix: 14 | rows: 3 15 | cols: 3 16 | data: [1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000] 17 | projection_matrix: 18 | rows: 3 19 | cols: 4 20 | data: [361.502411, 0.000000, 333.397355, 0.000000, 0.000000, 406.817780, 257.541316, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000] 21 | -------------------------------------------------------------------------------- /subt/ros/robot/params_common/costmap_common_params.yaml: -------------------------------------------------------------------------------- 1 | obstacle_range: 2.5 2 | raytrace_range: 3.0 3 | footprint: [[ 0.14, 0.16], [-0.14, 0.16], [-0.14, -0.16], [ 0.14, -0.16]] 4 | #footprint_padding: 0.05 5 | footprint_padding: 0.01 6 | #footprint: [[ 0, 0], [-0, 0], [-0, -0], [ 0, -0]] 7 | 8 | #robot_radius: ir_of_robot 9 | transform_tolerance: 1 10 | 11 | controller_patience: 2.0 12 | 13 | -------------------------------------------------------------------------------- /subt/ros/robot/params_common/ekf_params.yaml: -------------------------------------------------------------------------------- 1 | ekf_se_map: 2 | frequency: 10 3 | sensor_timeout: 0.1 4 | two_d_mode: true 5 | transform_time_offset: 0.2 6 | transform_timeout: 0.0 7 | print_diagnostics: true 8 | debug: false 9 | 10 | map_frame: map 11 | odom_frame: odom 12 | base_link_frame: base_link 13 | world_frame: map 14 | 15 | # ------------------------------------- 16 | # Wheel odometry: 17 | odom0: /odom 18 | # 19 | odom0_config: [false, false, false, 20 | false, false, false, 21 | true, true, false, 22 | false, false, true, 23 | false, false, false] 24 | odom0_queue_size: 10 25 | odom0_nodelay: true 26 | odom0_differential: false 27 | odom0_relative: false 28 | # ------------------------------------- 29 | # GPS odometry: 30 | odom1: /odometry/gps 31 | odom1_config: [true, true, false, 32 | false, false, false, 33 | false, false, false, 34 | false, false, false, 35 | false, false, false] 36 | odom1_queue_size: 10 37 | odom1_nodelay: true 38 | odom1_differential: false 39 | odom1_relative: false 40 | -------------------------------------------------------------------------------- /subt/ros/robot/params_common/global_costmap_params.yaml: -------------------------------------------------------------------------------- 1 | global_costmap: 2 | plugins: 3 | - {name: static, type: "costmap_2d::StaticLayer"} 4 | #- {name: inflation, type: "costmap_2d::InflationLayer"} 5 | - {name: staticlayer, type: "nav_layer_from_points::NavLayerFromPoints"} 6 | robot_base_frame: base_link 7 | global_frame: map 8 | update_frequency: 10.0 9 | publish_frequency: 10.0 10 | static_map: true 11 | resolution: 0.1 12 | 13 | inflation: 14 | inflation_radius: 0.3 15 | 16 | 17 | -------------------------------------------------------------------------------- /subt/ros/robot/params_common/local_costmap_params.yaml: -------------------------------------------------------------------------------- 1 | local_costmap: 2 | plugins: 3 | - {name: obstacles, type: "costmap_2d::ObstacleLayer"} 4 | - {name: staticlayer, type: "nav_layer_from_points::NavLayerFromPoints"} 5 | # assuming receiving a cloud from rtabmap_ros/obstacles_detection node 6 | 7 | 8 | global_frame: odom 9 | robot_base_frame: base_link 10 | update_frequency: 30.0 11 | publish_frequency: 30.0 12 | static_map: false 13 | rolling_window: true 14 | always_send_full_costmap: true 15 | width: 10.0 16 | height: 10.0 17 | resolution: 0.05 18 | origin_x: -5.0 19 | origin_y: -5.0 20 | track_unknown_space: false 21 | obstacles: 22 | publish_voxel_map: false 23 | observation_sources: laser_scan_sensor 24 | 25 | laser_scan_sensor: { 26 | sensor_frame: camera_link, 27 | data_type: LaserScan, 28 | topic: "/scan", 29 | expected_update_rate: 0.5, 30 | marking: true, 31 | clearing: true, 32 | inf_is_valid: false, #this must be false for depth_nav_tools 33 | min_obstacle_height: -99999.0, 34 | max_obstacle_height: 99999.0} 35 | -------------------------------------------------------------------------------- /subt/ros/robot/params_common/move_base_params.yaml: -------------------------------------------------------------------------------- 1 | # Move base node parameters. For full documentation of the parameters in this file, please see 2 | # 3 | # http://www.ros.org/wiki/move_base 4 | # 5 | shutdown_costmaps: false 6 | controller_frequency: 5.0 7 | controller_patience: 3.0 8 | 9 | 10 | planner_frequency: 1.0 11 | planner_patience: 5.0 12 | oscillation_timeout: 10.0 13 | oscillation_distance: 0.2 14 | 15 | # local planner - default is trajectory rollout 16 | base_local_planner: "dwa_local_planner/DWAPlannerROS" 17 | 18 | base_global_planner: "navfn/NavfnROS" #"global_planner/GlobalPlanner" #"voronoi_planner/VoronoiPlanner" #alternatives: global_planner/GlobalPlanner, carrot_planner/CarrotPlanner 19 | 20 | 21 | #We plan to integrate recovery behaviors for turtlebot but currently those belong to gopher and still have to be adapted. 22 | ## recovery behaviors; we avoid spinning, but we need a fall-back replanning 23 | recovery_behavior_enabled: false 24 | 25 | recovery_behaviors: 26 | - name: 'super_conservative_reset1' 27 | type: 'clear_costmap_recovery/ClearCostmapRecovery' 28 | - name: 'conservative_reset1' 29 | type: 'clear_costmap_recovery/ClearCostmapRecovery' 30 | - name: 'aggressive_reset1' 31 | type: 'clear_costmap_recovery/ClearCostmapRecovery' 32 | - name: 'clearing_rotation1' 33 | type: 'rotate_recovery/RotateRecovery' 34 | 35 | super_conservative_reset1: 36 | reset_distance: 3.0 37 | conservative_reset1: 38 | reset_distance: 1.5 39 | aggressive_reset1: 40 | reset_distance: 0.0 41 | -------------------------------------------------------------------------------- /subt/ros/robot/params_eduro/cliff_detector_params.yaml: -------------------------------------------------------------------------------- 1 | output_frame_id: camera_link 2 | rate: 10 3 | range_min: 0.5 4 | range_max: 5.0 5 | sensor_mount_height: 0.365 6 | sensor_tilt_angle: -5.0 7 | 8 | publish_depth: true 9 | cam_model_update: false 10 | used_depth_height: 200 11 | block_size: 16 12 | block_points_thresh: 3 13 | depth_img_step_row: 8 14 | depth_img_step_col: 8 15 | ground_margin: 0.15 16 | -------------------------------------------------------------------------------- /subt/ros/robot/params_eduro/depth_scan_params.yaml: -------------------------------------------------------------------------------- 1 | # Frame id for the output laserscan. 2 | output_frame_id: camera_link 3 | # Minimum sensor range (m). 4 | range_min: 0.2 5 | # Maximum sensor range (m). 6 | range_max: 10.0 7 | # Height of used part of depth img (px). 8 | scan_height: 400 9 | # Row step in depth image processing (px). 10 | depth_img_row_step: 1 11 | # If continously camera data update. 12 | cam_model_update: false 13 | 14 | # Height of sensor optical center mount (m). 15 | sensor_mount_height: 0.365 16 | # Sensor tilt angle compensation. 17 | sensor_tilt_angle: 3.0 18 | # Remove ground from scan. 19 | ground_remove_en: true 20 | # Ground margin (m). 21 | ground_margin: 0.12 22 | # Sensor tilt angle compensation. 23 | tilt_compensation_en: true 24 | 25 | -------------------------------------------------------------------------------- /subt/ros/robot/params_k2/cliff_detector_params.yaml: -------------------------------------------------------------------------------- 1 | output_frame_id: camera_link 2 | rate: 10 3 | range_min: 0.5 4 | range_max: 5.0 5 | sensor_mount_height: 0.245 6 | sensor_tilt_angle: -5.0 7 | 8 | publish_depth: true 9 | cam_model_update: false 10 | used_depth_height: 200 11 | block_size: 16 12 | block_points_thresh: 3 13 | depth_img_step_row: 8 14 | depth_img_step_col: 8 15 | ground_margin: 0.15 16 | -------------------------------------------------------------------------------- /subt/ros/robot/params_k2/depth_scan_params.yaml: -------------------------------------------------------------------------------- 1 | # Frame id for the output laserscan. 2 | output_frame_id: camera_link 3 | # Minimum sensor range (m). 4 | range_min: 0.2 5 | # Maximum sensor range (m). 6 | range_max: 10.0 7 | # Height of used part of depth img (px). 8 | scan_height: 400 9 | # Row step in depth image processing (px). 10 | depth_img_row_step: 1 11 | # If continously camera data update. 12 | cam_model_update: false 13 | 14 | # Height of sensor optical center mount (m). 15 | sensor_mount_height: 0.245 16 | # Sensor tilt angle compensation. 17 | sensor_tilt_angle: 5.0 18 | # Remove ground from scan. 19 | ground_remove_en: true 20 | # Ground margin (m). 21 | ground_margin: 0.13 22 | # Sensor tilt angle compensation. 23 | tilt_compensation_en: true 24 | 25 | -------------------------------------------------------------------------------- /subt/ros/robot/params_maria/cliff_detector_params.yaml: -------------------------------------------------------------------------------- 1 | output_frame_id: camera_link 2 | rate: 10 3 | range_min: 0.5 4 | range_max: 5.0 5 | sensor_mount_height: 0.19 6 | sensor_tilt_angle: -5.0 7 | 8 | publish_depth: true 9 | cam_model_update: false 10 | used_depth_height: 200 11 | block_size: 16 12 | block_points_thresh: 3 13 | depth_img_step_row: 8 14 | depth_img_step_col: 8 15 | ground_margin: 0.15 16 | -------------------------------------------------------------------------------- /subt/ros/robot/params_maria/depth_scan_params.yaml: -------------------------------------------------------------------------------- 1 | # Frame id for the output laserscan. 2 | output_frame_id: camera_link 3 | # Minimum sensor range (m). 4 | range_min: 0.2 5 | # Maximum sensor range (m). 6 | range_max: 10.0 7 | # Height of used part of depth img (px). 8 | scan_height: 400 9 | # Row step in depth image processing (px). 10 | depth_img_row_step: 1 11 | # If continously camera data update. 12 | cam_model_update: false 13 | 14 | # Height of sensor optical center mount (m). 15 | sensor_mount_height: 0.19 16 | # Sensor tilt angle compensation. 17 | sensor_tilt_angle: 5.0 18 | # Remove ground from scan. 19 | ground_remove_en: true 20 | # Ground margin (m). 21 | ground_margin: 0.1 22 | # Sensor tilt angle compensation. 23 | tilt_compensation_en: true 24 | 25 | -------------------------------------------------------------------------------- /subt/ros/robot/params_mob/camera_calibration.yaml: -------------------------------------------------------------------------------- 1 | image_width: 640 2 | image_height: 480 3 | camera_name: narrow_stereo 4 | camera_matrix: 5 | rows: 3 6 | cols: 3 7 | data: [447.464054, 0.000000, 330.673909, 0.000000, 453.975988, 254.771887, 0.000000, 0.000000, 1.000000] 8 | distortion_model: plumb_bob 9 | distortion_coefficients: 10 | rows: 1 11 | cols: 5 12 | data: [-0.336467, 0.116057, -0.001453, -0.001215, 0.000000] 13 | rectification_matrix: 14 | rows: 3 15 | cols: 3 16 | data: [1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000] 17 | projection_matrix: 18 | rows: 3 19 | cols: 4 20 | data: [361.502411, 0.000000, 333.397355, 0.000000, 0.000000, 406.817780, 257.541316, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000] 21 | -------------------------------------------------------------------------------- /subt/ros/robot/params_mob/cliff_detector_params.yaml: -------------------------------------------------------------------------------- 1 | output_frame_id: camera_link 2 | rate: 10 3 | range_min: 0.5 4 | range_max: 5.0 5 | sensor_mount_height: 0.3 6 | sensor_tilt_angle: -5.0 7 | 8 | publish_depth: true 9 | cam_model_update: false 10 | used_depth_height: 200 11 | block_size: 16 12 | block_points_thresh: 3 13 | depth_img_step_row: 8 14 | depth_img_step_col: 8 15 | ground_margin: 0.15 16 | -------------------------------------------------------------------------------- /subt/ros/robot/params_mob/costmap_common_params.yaml: -------------------------------------------------------------------------------- 1 | obstacle_range: 2.5 2 | raytrace_range: 3.0 3 | footprint: [[ 0.14, 0.16], [-0.14, 0.16], [-0.14, -0.16], [ 0.14, -0.16]] 4 | #footprint_padding: 0.05 5 | footprint_padding: 0.01 6 | #footprint: [[ 0, 0], [-0, 0], [-0, -0], [ 0, -0]] 7 | 8 | #robot_radius: ir_of_robot 9 | transform_tolerance: 1 10 | 11 | controller_patience: 2.0 12 | 13 | -------------------------------------------------------------------------------- /subt/ros/robot/params_mob/depth_scan_params.yaml: -------------------------------------------------------------------------------- 1 | # Frame id for the output laserscan. 2 | output_frame_id: camera_link 3 | # Minimum sensor range (m). 4 | range_min: 0.2 5 | # Maximum sensor range (m). 6 | range_max: 10.0 7 | # Height of used part of depth img (px). 8 | scan_height: 400 9 | # Row step in depth image processing (px). 10 | depth_img_row_step: 1 11 | # If continously camera data update. 12 | cam_model_update: false 13 | 14 | # Height of sensor optical center mount (m). 15 | sensor_mount_height: 0.29 16 | # Sensor tilt angle compensation. 17 | sensor_tilt_angle: 5.0 18 | # Remove ground from scan. 19 | ground_remove_en: true 20 | # Ground margin (m). 21 | ground_margin: 0.1 22 | # Sensor tilt angle compensation. 23 | tilt_compensation_en: true 24 | 25 | -------------------------------------------------------------------------------- /subt/ros/robot/params_mob/ekf_params.yaml: -------------------------------------------------------------------------------- 1 | ekf_se_map: 2 | frequency: 10 3 | sensor_timeout: 0.1 4 | two_d_mode: true 5 | transform_time_offset: 0.2 6 | transform_timeout: 0.0 7 | print_diagnostics: true 8 | debug: false 9 | 10 | map_frame: map 11 | odom_frame: odom 12 | base_link_frame: base_link 13 | world_frame: map 14 | 15 | # ------------------------------------- 16 | # Wheel odometry: 17 | odom0: /odom 18 | # 19 | odom0_config: [false, false, false, 20 | false, false, false, 21 | true, true, false, 22 | false, false, true, 23 | false, false, false] 24 | odom0_queue_size: 10 25 | odom0_nodelay: true 26 | odom0_differential: false 27 | odom0_relative: false 28 | # ------------------------------------- 29 | # GPS odometry: 30 | odom1: /odometry/gps 31 | odom1_config: [true, true, false, 32 | false, false, false, 33 | false, false, false, 34 | false, false, false, 35 | false, false, false] 36 | odom1_queue_size: 10 37 | odom1_nodelay: true 38 | odom1_differential: false 39 | odom1_relative: false 40 | -------------------------------------------------------------------------------- /subt/ros/robot/params_mob/global_costmap_params.yaml: -------------------------------------------------------------------------------- 1 | global_costmap: 2 | plugins: 3 | - {name: static, type: "costmap_2d::StaticLayer"} 4 | #- {name: inflation, type: "costmap_2d::InflationLayer"} 5 | - {name: staticlayer, type: "nav_layer_from_points::NavLayerFromPoints"} 6 | robot_base_frame: base_link 7 | global_frame: odom 8 | update_frequency: 10.0 9 | publish_frequency: 10.0 10 | static_map: true 11 | resolution: 0.1 12 | 13 | inflation: 14 | inflation_radius: 0.3 15 | 16 | 17 | -------------------------------------------------------------------------------- /subt/ros/robot/params_mob/local_costmap_params.yaml: -------------------------------------------------------------------------------- 1 | local_costmap: 2 | plugins: 3 | - {name: obstacles, type: "costmap_2d::ObstacleLayer"} 4 | - {name: staticlayer, type: "nav_layer_from_points::NavLayerFromPoints"} 5 | # assuming receiving a cloud from rtabmap_ros/obstacles_detection node 6 | 7 | 8 | global_frame: odom 9 | robot_base_frame: base_link 10 | update_frequency: 30.0 11 | publish_frequency: 30.0 12 | static_map: false 13 | rolling_window: true 14 | always_send_full_costmap: true 15 | width: 10.0 16 | height: 10.0 17 | resolution: 0.05 18 | origin_x: -5.0 19 | origin_y: -5.0 20 | track_unknown_space: false 21 | obstacles: 22 | publish_voxel_map: false 23 | observation_sources: laser_scan_sensor 24 | 25 | laser_scan_sensor: { 26 | sensor_frame: camera_link, 27 | data_type: LaserScan, 28 | topic: "/scan", 29 | expected_update_rate: 0.5, 30 | marking: true, 31 | clearing: true, 32 | inf_is_valid: false, #this must be false for depth_nav_tools 33 | min_obstacle_height: -99999.0, 34 | max_obstacle_height: 99999.0} 35 | -------------------------------------------------------------------------------- /subt/ros/robot/src/filter_depth.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import numpy as np 4 | import sys 5 | 6 | import cv_bridge 7 | import rospy 8 | from sensor_msgs.msg import Image 9 | 10 | class FilterDepth: 11 | def __init__(self, min_depth, max_depth): 12 | self.min_depth = min_depth 13 | self.max_depth = max_depth 14 | 15 | self.subscriber = rospy.Subscriber('input', Image, self.depthCallback) 16 | self.publisher = rospy.Publisher("output", Image, queue_size=10) 17 | 18 | self.cv_bridge = cv_bridge.CvBridge() 19 | 20 | 21 | def depthCallback(self, input_msg): 22 | input_depth = self.cv_bridge.imgmsg_to_cv2( 23 | input_msg, desired_encoding='passthrough') 24 | output_depth = np.where( 25 | np.logical_and(input_depth >= self.min_depth, 26 | input_depth <= self.max_depth), 27 | input_depth, 28 | np.inf) 29 | output_msg = self.cv_bridge.cv2_to_imgmsg( 30 | output_depth, encoding="passthrough") 31 | output_msg.header = input_msg.header 32 | self.publisher.publish(output_msg) 33 | 34 | 35 | if __name__ == "__main__": 36 | rospy.init_node("filter_depth", log_level=rospy.DEBUG) 37 | overrider = FilterDepth(*[float(limit) for limit in rospy.myargv(sys.argv)[1:3]]) 38 | rospy.spin() 39 | -------------------------------------------------------------------------------- /subt/ros/robot/src/laserscan_to_pointcloud.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import rospy 4 | from sensor_msgs.msg import PointCloud2, LaserScan 5 | from laser_geometry import LaserProjection 6 | 7 | class LaserScanToPointCloud: 8 | def __init__(self): 9 | self.laserProj = LaserProjection() 10 | self.pointCloudPublisher = rospy.Publisher("/points", PointCloud2, queue_size = 1) 11 | self.laserScanSubscriber = rospy.Subscriber("/scan", LaserScan, self.laserScanCallback) 12 | 13 | def laserScanCallback(self, data): 14 | self.pointCloudPublisher.publish(self.laserProj.projectLaser(data)) 15 | 16 | 17 | 18 | if __name__ == "__main__": 19 | rospy.init_node("LaserScanToPointCloud") 20 | laserScanToPointCloud = LaserScanToPointCloud() 21 | rospy.spin() 22 | 23 | -------------------------------------------------------------------------------- /subt/ros/robot/test/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from osgar.lib import create_load_tests 4 | load_tests = create_load_tests(__file__) 5 | -------------------------------------------------------------------------------- /subt/ros/straight_drive/launch/straight_drive.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /subt/ros/straight_drive/src/straight_drive.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import rospy 4 | from geometry_msgs.msg import Twist 5 | 6 | 7 | SPEED = 0.2 8 | 9 | 10 | rospy.init_node("straight_drive",log_level=rospy.DEBUG) 11 | velocity_publisher = rospy.Publisher('/cmd_vel', Twist, queue_size=10) 12 | vel_msg = Twist() 13 | vel_msg.linear.x = SPEED 14 | vel_msg.linear.y = 0 15 | vel_msg.linear.z = 0 16 | vel_msg.angular.x = 0 17 | vel_msg.angular.y = 0 18 | vel_msg.angular.z = 0 19 | 20 | r = rospy.Rate(10) # 10hz 21 | while not rospy.is_shutdown(): 22 | velocity_publisher.publish(vel_msg) 23 | r.sleep() 24 | -------------------------------------------------------------------------------- /subt/script/bridge.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | termtitle() { printf "\033]0;$*\007"; } 4 | 5 | trap "kill %1" EXIT 6 | 7 | ROBOT="${ROBOT:-X200L}" 8 | WORLD="${WORLD:-urban_circuit_practice_01}" 9 | 10 | case $WORLD in 11 | *"urban"*): 12 | CIRCUIT="urban" ;; 13 | *"cave"*): 14 | CIRCUIT="cave"; ;; 15 | *"tunnel"*): 16 | CIRCUIT="tunnel" ;; 17 | *"final"*): 18 | CIRCUIT="finals" ;; 19 | *"niosh"*): 20 | CIRCUIT="niosh" ;; 21 | *): 22 | echo "circuit not detected"; 23 | exit 1;; 24 | esac 25 | 26 | CONFIG="${CONFIG:-ROBOTIKA_X2_SENSOR_CONFIG_1}" 27 | 28 | ( while true; do termtitle "bridge $ROBOT $WORLD"; sleep 5; done ) & 29 | 30 | cd $(git rev-parse --show-toplevel) 31 | 32 | DOCKER_OPTS="--name bridge" 33 | export DOCKER_OPTS 34 | 35 | echo circuit: $CIRCUIT; echo robot: $ROBOT; echo world: $WORLD; 36 | 37 | ./subt/docker/run.bash osrf/subt-virtual-testbed:cloudsim_bridge_latest \ 38 | circuit:=$CIRCUIT \ 39 | worldName:=$WORLD \ 40 | robotName1:=$ROBOT \ 41 | robotConfig1:=$CONFIG 42 | 43 | -------------------------------------------------------------------------------- /subt/script/build-and-install-ros-packages.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e # Exit on any error. 4 | 5 | PKGS_SRC_PATH=$(dirname "$0")/../ros 6 | CATKIN_DEVEL_PATH=ros.devel.tmp 7 | INSTALL_PATH=ros/subt 8 | echo "Building Osgar SubT ROS modules ..." 9 | catkin_make --source "${PKGS_SRC_PATH}" -DCATKIN_DEVEL_PREFIX="${CATKIN_DEVEL_PATH}" -DCMAKE_INSTALL_PREFIX="${INSTALL_PATH}" 10 | echo "Installing Osgar SubT ROS modules ..." 11 | catkin_make install --source "${PKGS_SRC_PATH}" -DCATKIN_DEVEL_PREFIX="${CATKIN_DEVEL_PATH}" -DCMAKE_INSTALL_PREFIX="${INSTALL_PATH}" 12 | echo "Osgar SubT ROS modules are installed in \"${INSTALL_PATH}\"." 13 | -------------------------------------------------------------------------------- /subt/script/check-artf.bat: -------------------------------------------------------------------------------- 1 | cd artf 2 | python -m osgar.replay --module detector %1 3 | cd .. 4 | python -m subt.check_phone %1 5 | -------------------------------------------------------------------------------- /subt/script/check_rosK2.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ssh -t k2jetson "source /opt/ros/melodic/setup.bash;source ~/ros_ws/devel/setup.bash; roslaunch robot k2.launch" 3 | -------------------------------------------------------------------------------- /subt/script/check_rosK3.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ssh -t k3jetson "source /opt/ros/melodic/setup.bash;source ~/ros_ws/devel/setup.bash; roslaunch robot k3.launch" 3 | -------------------------------------------------------------------------------- /subt/script/debug-virtual-view.bat: -------------------------------------------------------------------------------- 1 | python -m osgar.tools.lidarview --pose2d app.pose2d --lidar fromrospy.scan360 --rgbd detector.debug_rgbd --keyframes detector.localized_artf --title rosmsg.sim_time_sec %* 2 | -------------------------------------------------------------------------------- /subt/script/devel.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "$(git rev-parse --show-toplevel)" || exit 4 | 5 | DIR=$(pwd) 6 | 7 | DOCKER_OPTS="--volume ${DIR}:/osgar-ws/src/osgar --name devel" 8 | export DOCKER_OPTS 9 | 10 | ./subt/docker/run.bash robotika:latest bash 11 | -------------------------------------------------------------------------------- /subt/script/eduro-view.bat: -------------------------------------------------------------------------------- 1 | python -m osgar.tools.lidarview --lidar lidar.scan --camera camera.raw --pose2d app.pose2d --keyframes detector.artf %* 2 | -------------------------------------------------------------------------------- /subt/script/kloubak-view.bat: -------------------------------------------------------------------------------- 1 | python -m osgar.tools.lidarview --lidar lidar.scan --lidar2 lidar_back.scan --camera camera.raw --camera2 camera_back.raw --pose2d app.pose2d --keyframes detector.artf --joint kloubak.joint_angle %* 2 | -------------------------------------------------------------------------------- /subt/script/mobos-view.bat: -------------------------------------------------------------------------------- 1 | python -m osgar.tools.lidarview --pose2d app.pose2d --lidar rosmsg.scan --camera rosmsg.image --camera2 rosmsg.depth --title rosmsg.sim_time_sec %* 2 | -------------------------------------------------------------------------------- /subt/script/rear-artf.bat: -------------------------------------------------------------------------------- 1 | cd artf 2 | python -m osgar.replay --module detector %1 --config ..\subt\script\rear-k2-sensors.json -F 3 | cd .. 4 | 5 | -------------------------------------------------------------------------------- /subt/script/robik-view.bat: -------------------------------------------------------------------------------- 1 | python -m osgar.tools.lidarview --lidar cortexpilot.scan --camera camera_orange.raw --camera2 camera_green.raw --pose2d app.pose2d --keyframes detector.artf --deg 360 %* 2 | -------------------------------------------------------------------------------- /subt/script/run_deedee.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source ros/subt/setup.bash 4 | export PYTHONPATH=${PWD}:${PYTHONPATH} 5 | python3 -m subt --use-old-record run config/deedee-subt.json --side left --speed 0.2 --timeout 1200 --wall-dist 0.5 --gap-size 0.6 6 | -------------------------------------------------------------------------------- /subt/script/run_eduro_ros.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | trap "exit;" HUP INT TERM 4 | trap "kill 0" EXIT 5 | (python -m subt run config/eduro-subt-estop-lora-wifi-jetson.json --side right --speed 0.7 --gap-size 0.6 --wall-dist 0.6 --timeout 300 --start-paused ; python -m osgar.record config/test-lora.json) & 6 | ssh -t edurojetson "source /opt/ros/melodic/setup.bash;source ~/ros_ws/devel/setup.bash; roslaunch robot eduro.launch" 7 | wait 8 | 9 | -------------------------------------------------------------------------------- /subt/script/run_jetson_front.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source ros/subt/setup.bash 4 | python3 -m osgar.record config/jetson-node-k2-front.json 5 | -------------------------------------------------------------------------------- /subt/script/run_kloubak2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | python -m subt run config/kloubak2-subt-estop-lora.json --side left --speed 0.7 --timeout 1200 4 | python -m osgar.record config/test-lora.json 5 | -------------------------------------------------------------------------------- /subt/script/run_kloubak2_jetson.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function trap_ctrlc_rear () 4 | { 5 | ssh -t k2jetson_rear "pkill -15 -f 'osgar.record'" 6 | exit 2 7 | } 8 | 9 | (python -m subt --use-old-record run config/kloubak2-subt-estop-lora-jetson.json --side left --speed 0.5 --timeout 1200 --gap-size 0.6 --wall-dist 0.6 --init-path "8.0,0.0"; python -m osgar.record config/test-lora.json) & 10 | 11 | trap "trap_ctrlc_rear" 2 12 | ssh -t k2jetson_rear "python3 -m osgar.record ~/git/osgar/config/jetson-node-k2-rear.json" & 13 | ssh -t k2jetson_front "cd git/osgar && ./subt/script/run_jetson_front.bash" 14 | wait 15 | -------------------------------------------------------------------------------- /subt/script/run_kloubak2_ros.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | trap "exit;" HUP INT TERM 4 | trap "kill 0" EXIT 5 | (python -m subt run config/kloubak2-subt-estop-lora-jetson.json --side left --speed 0.7 --timeout 1200 --start-paused; python -m osgar.record config/test-lora.json) & 6 | ssh -t k2jetson "source /opt/ros/melodic/setup.bash;source ~/ros_ws/devel/setup.bash; roslaunch robot k2.launch" 7 | wait 8 | -------------------------------------------------------------------------------- /subt/script/run_kloubak3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | python -m subt run config/kloubak3-subt-estop-lora.json --side left --speed 0.7 --timeout 300 4 | #python -m osgar.go config/kloubak3-subt-estop-lora.json -d 4 --timeout 20 5 | python -m osgar.record config/test-lora.json 6 | -------------------------------------------------------------------------------- /subt/script/run_kloubak3_ros.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | trap "exit;" HUP INT TERM 4 | trap "kill 0" EXIT 5 | (python -m subt run config/kloubak3-subt-estop-lora-jetson.json --side left --speed 0.7 --timeout 120 --gap-size 0.6 --wall-dist 0.6; python -m osgar.record config/test-lora.json) & 6 | ssh -t k3jetson "source /opt/ros/melodic/setup.bash;source ~/ros_ws/devel/setup.bash; roslaunch robot k3.launch" 7 | wait 8 | -------------------------------------------------------------------------------- /subt/script/run_maria.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #(python3 -m subt.main run config/maria-ros.json --side right --speed 0.5 --gap-size 0.7 --wall-dist 0.7 ;python3 -m osgar.record config/test-lora.json) & 4 | #FIRST ROUND: (python3 -m subt.main run config/maria-ros.json --side left --speed 0.5 --gap-size 0.7 --wall-dist 0.7 --init-offset="-2.5,0,0" --start-paused;python3 -m osgar.record config/test-lora.json) & 5 | 6 | 7 | (python3 -m subt.main run config/maria-ros.json --side left --speed 0.5 -gap-size --wall-dist 0.6 --init-offset="-2.5,0,0" ;python3 -m osgar.record config/test-lora.json) & 8 | roslaunch robot maria.launch 9 | 10 | wait 11 | 12 | -------------------------------------------------------------------------------- /subt/script/run_mobos.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #FIRST ROUND (python3 -m subt.main run config/mobos-ros.json --start-paused --side right --speed 0.5 --gap-size 0.6 --wall-dist 0.6 --init-offset="-2.5,0,0" --init-path="3, 0; 3, 3";python3 -m osgar.record config/test-lora.json) & 4 | 5 | #SECOND ROUND (python3 -m subt.main run config/mobos-ros.json --side right --speed 0.5 --gap-size 0.6 --wall-dist 0.6 --init-offset="-2.5,0,0";python3 -m osgar.record config/test-lora.json) & 6 | 7 | python3 -m subt.main run config/mobos-ros.json --side left --speed 0.5 --gap-size 0.6 --wall0dist 0.6 & 8 | roslaunch robot auto_mob.launch 9 | 10 | wait 11 | 12 | -------------------------------------------------------------------------------- /subt/script/run_skiddy.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source ros/subt/setup.bash 4 | export PYTHONPATH=${PWD}:${PYTHONPATH} 5 | export OMP_NUM_THREADS=1 # Make OpenCV eat fewer cpus. 6 | python3 -m osgar.record config/skiddy-subt-serialloop.json & 7 | pidcore=$! 8 | python3 -m subt.main --use-old-record run config/skiddy-subt.json --side right --speed 0.4 --timeout 900 --wall-dist 0.6 --gap-size 0.6 --init-path "15.0,0" 9 | #python3 -m osgar.go run config/skiddy-subt.json -s 0.3 -d -4 --timeout 30 10 | kill "$pidcore" 11 | -------------------------------------------------------------------------------- /subt/script/teleop.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Waiting for robot name" 4 | while [ -z "$ROBOT_NAME" ]; do 5 | ROBOT_NAME=$(rosparam get /robot_names 2>/dev/null) 6 | sleep 0.5 7 | done 8 | echo "Robot name is '$ROBOT_NAME'" 9 | 10 | /opt/ros/melodic/lib/teleop_twist_keyboard/teleop_twist_keyboard.py cmd_vel:=/${ROBOT_NAME}/cmd_vel_osgar __name:=keyboard 11 | -------------------------------------------------------------------------------- /subt/script/vesc-odo.bat: -------------------------------------------------------------------------------- 1 | python -m osgar.replay --module vesc --verbose --draw %1 2 | vesc.txt 3 | -------------------------------------------------------------------------------- /subt/script/virtual-depth-view.bat: -------------------------------------------------------------------------------- 1 | python -m osgar.tools.lidarview --pose2d app.pose2d --lidar depth2scan.scan --camera logimage.image --camera2 logimage.depth --keyframes detector.localized_artf --title rosmsg.sim_time_sec %* 2 | -------------------------------------------------------------------------------- /subt/script/virtual-view.bat: -------------------------------------------------------------------------------- 1 | python -m osgar.tools.lidarview --pose2d app.pose2d --lidar rosmsg.scan --camera rosmsg.image --keyframes detector.artf --title rosmsg.sim_time_sec %* 2 | -------------------------------------------------------------------------------- /subt/submission/cave-circuit.toml: -------------------------------------------------------------------------------- 1 | world = "cc" 2 | timeout = 4000 3 | image = "ver92" 4 | 5 | [robots] 6 | A100W900LH700RH3600W = "drone" 7 | B700W600LH400RH3600W = "drone" 8 | C120W1500RH1300LH3600W = "freyja" 9 | D0W1700RH1500LH3600W = "freyja" 10 | E60W1750LH1550RH3600W = "freyja" 11 | F1000W600RH400LH3600W = "drone" 12 | G300W900RH700LH3600W = "drone" 13 | H0W1050RH850LH3600W = "drone" 14 | 15 | -------------------------------------------------------------------------------- /subt/submission/finals.toml: -------------------------------------------------------------------------------- 1 | world = "fr" 2 | timeout = 4000 3 | image = "ver133" 4 | 5 | [robots] 6 | D390W2C1500LH3600W = "freyja" 7 | B90W2C2400LH3600W = "freyja" 8 | A0W2C2400RH3600W = "freyja" 9 | C300W2C1500RH3600W = "freyja" 10 | E600W900LH3600W = "pam" 11 | H1980W600RH3600W = "pam" 12 | G1920W600LH3600W = "pam" 13 | F660W900RH3600W = "pam" 14 | 15 | -------------------------------------------------------------------------------- /subt/submission/two-freyjas.toml: -------------------------------------------------------------------------------- 1 | world = "fp1" 2 | timeout = 2000 3 | image = "ver101cuda" 4 | 5 | [robots] 6 | A900L = "freyja" 7 | B900R = "freyja" 8 | 9 | -------------------------------------------------------------------------------- /subt/subt-freyja.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "init": { 7 | "robot_width": 0.7, 8 | "limit_pitch": 40, 9 | "limit_roll": 40, 10 | "return_limit_pitch": 50, 11 | "return_limit_roll": 50, 12 | "obstacle_influence": 1.4, 13 | "speed_policy": "conservative", 14 | "min_safe_dist": 0.8, 15 | "dangerous_dist": 0.5, 16 | "turbo_safe_dist": 2.8, 17 | "turbo_speed": 2.2, 18 | "rotation_p": 1.6, 19 | "follow_wall": { 20 | "internal_reflection_threshold": 0 21 | } 22 | } 23 | }, 24 | "detector": { 25 | "init": { 26 | "fx": 349.2, 27 | "batch_size": 2 28 | } 29 | }, 30 | "detector_lr": { 31 | "init": { 32 | "fx": 149.01, 33 | "batch_size": 2 34 | } 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /subt/subt-k2-virt.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "robot": { 4 | "modules": { 5 | "app": { 6 | "init": { 7 | "limit_pitch": 45, 8 | "limit_roll": 40, 9 | "return_limit_pitch": 50, 10 | "return_limit_roll": 50, 11 | "rotation_p": 0.6, 12 | "obstacle_influence": 0.8 13 | } 14 | }, 15 | "detector": { 16 | "init": { 17 | "fx": 337.22 18 | } 19 | }, 20 | "detector_rear": { 21 | "init": { 22 | "fx": 337.22 23 | } 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /subt/test_artf_gas.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from unittest.mock import MagicMock, call 3 | 4 | from subt.artf_gas import ArtifactGasDetector 5 | from subt.artifacts import GAS 6 | 7 | 8 | class ArtifactGasDetectorTest(unittest.TestCase): 9 | 10 | def test_report(self): 11 | bus = bus=MagicMock() 12 | detector = ArtifactGasDetector(bus=bus, config={}) 13 | detector.on_pose3d([[1, 2, 3], [0, 0, 0, 1]]) 14 | detector.on_gas_detected(False) 15 | bus.publish.assert_not_called() 16 | 17 | detector.on_pose3d([[1, 0, 1], [0, 0, 0, 1]]) 18 | detector.on_gas_detected(True) 19 | bus.publish.assert_called() 20 | bus.publish.assert_has_calls([call('localized_artf', [GAS, [1.0, 0, 1.0]])]) 21 | 22 | def test_drone_z(self): 23 | # the location point is on the ground level, which is OK for ground vehicles but not for drones 24 | bus = bus=MagicMock() 25 | detector = ArtifactGasDetector(bus=bus, config={}) 26 | detector.on_pose3d([[1, 2, 3], [0, 0, 0, 1]]) 27 | detector.on_gas_detected(False) 28 | detector.on_pose3d([[1, 0, 1], [0, 0, 0, 1]]) 29 | detector.on_bottom_scan([1.0]) # top/bottom scans are in meters 30 | 31 | bus.publish.reset_mock() 32 | detector.on_gas_detected(True) 33 | bus.publish.assert_called() 34 | bus.publish.assert_has_calls([call('localized_artf', [GAS, [1.0, 0, 1.0 - 1.0]])]) 35 | 36 | 37 | # vim: expandtab sw=4 ts=4 38 | -------------------------------------------------------------------------------- /subt/test_data/artf-electrical-box.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotika/osgar/ab10ba4004329dcc0ea1ffc68ac2334bb1995c38/subt/test_data/artf-electrical-box.jpg -------------------------------------------------------------------------------- /subt/test_data/artf-extinguisher-hd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotika/osgar/ab10ba4004329dcc0ea1ffc68ac2334bb1995c38/subt/test_data/artf-extinguisher-hd.jpg -------------------------------------------------------------------------------- /subt/test_data/artf-toolbox.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotika/osgar/ab10ba4004329dcc0ea1ffc68ac2334bb1995c38/subt/test_data/artf-toolbox.jpg -------------------------------------------------------------------------------- /subt/test_data/artf-valve-hd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotika/osgar/ab10ba4004329dcc0ea1ffc68ac2334bb1995c38/subt/test_data/artf-valve-hd.jpg -------------------------------------------------------------------------------- /subt/test_data/artf-valve2-hd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotika/osgar/ab10ba4004329dcc0ea1ffc68ac2334bb1995c38/subt/test_data/artf-valve2-hd.jpg -------------------------------------------------------------------------------- /subt/test_data/freyja-octomap.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotika/osgar/ab10ba4004329dcc0ea1ffc68ac2334bb1995c38/subt/test_data/freyja-octomap.bin -------------------------------------------------------------------------------- /subt/test_data/rgbd.npz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotika/osgar/ab10ba4004329dcc0ea1ffc68ac2334bb1995c38/subt/test_data/rgbd.npz -------------------------------------------------------------------------------- /subt/test_depth2scan.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import math 3 | 4 | import numpy as np 5 | 6 | from subt.depth2scan import vertical_step, monotize, find_step 7 | 8 | 9 | class Depth2ScanTest(unittest.TestCase): 10 | 11 | def test_vertical_step(self): 12 | depth = np.zeros((360, 640), dtype=np.float32) 13 | self.assertIsNone(vertical_step(depth)) 14 | 15 | depth[:, 320] = np.arange(0, 4*360, 4)/1000.0 16 | #self.assertIsNone(vertical_step(depth)) 17 | 18 | depth = np.zeros((360, 640), dtype=np.float32) 19 | depth[:,:] = 0.2 20 | for i in range(180, 250): 21 | depth[i, 320] = 0.4 22 | self.assertEqual(vertical_step(depth), 200) # TODO better example 23 | 24 | def test_monotize(self): 25 | a = np.zeros(10, dtype=np.int32) 26 | np.testing.assert_equal(monotize(a), a) 27 | a[7] = 13 28 | self.assertEqual(monotize(a)[-1], 13) 29 | 30 | def test_find_step(self): 31 | self.assertIsNone(find_step(np.zeros(250, dtype=np.int32))) 32 | 33 | arr = np.zeros(250, dtype=np.int32) 34 | arr[100:] = 200 # wooden crate 20cm high 35 | self.assertEqual(find_step(arr), 100) 36 | 37 | # vim: expandtab sw=4 ts=4 38 | 39 | -------------------------------------------------------------------------------- /subt/test_dummy_darpa_server.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import os.path 3 | from subt.dummy_darpa_server import GameLogic, dist3d 4 | 5 | 6 | class DummyDarpaServerTest(unittest.TestCase): 7 | 8 | def test_game_logic(self): 9 | filename = os.path.join(os.path.dirname(__file__), 'config', 'darpa-artf.csv') 10 | # content 11 | """ 12 | artf, x, y, z 13 | Backpack, 2, -21.2, 0.5 14 | Cell Phone, 5, 5, 5 15 | """ 16 | game = GameLogic(filename) 17 | self.assertEqual(game.score, 0) 18 | 19 | self.assertTrue(game.report_artf('Cell Phone', (5, 5, 5))) # exact match 20 | self.assertEqual(game.score, 1) 21 | 22 | self.assertFalse(game.report_artf('Cell Phone', (5, 5, 5))) # already reported 23 | 24 | def test_dist3d(self): 25 | self.assertAlmostEqual(dist3d((0, 0, 0), (1, 0, 0)), 1.0) 26 | self.assertAlmostEqual(dist3d((1, 2, 3), (1+3, 2+4, 3)), 5.0) 27 | 28 | 29 | # vim: expandtab sw=4 ts=4 30 | 31 | -------------------------------------------------------------------------------- /subt/test_launch.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import unittest 3 | import unittest.mock 4 | 5 | from . import launch 6 | 7 | 8 | class Test(unittest.TestCase): 9 | def Xtest_launch(self): 10 | p = launch.Launch(config={'command': ['true']}, bus=unittest.mock.MagicMock()) 11 | p.start() 12 | p.join() 13 | 14 | def Xtest_request_stop(self): 15 | p = launch.Launch(config={'command': ['sleep', '10']}, bus=unittest.mock.MagicMock()) 16 | p.start() 17 | p.request_stop() 18 | p.join(0.1) 19 | 20 | def Xtest_join(self): 21 | with self.assertLogs(level=logging.WARNING) as log: 22 | p = launch.Launch(config={'command': ['sleep', '10']}, bus=unittest.mock.MagicMock()) 23 | p.start() 24 | p.join(0.1) 25 | self.assertEqual(len(log.records), 1) 26 | 27 | def Xtest_shell(self): 28 | with self.assertLogs(level=logging.WARNING) as log: 29 | p = launch.Launch(config={'command': 'sleep 10', 'shell': True}, bus=unittest.mock.MagicMock()) 30 | p.start() 31 | p.join(0.1) 32 | self.assertEqual(len(log.records), 1) 33 | -------------------------------------------------------------------------------- /subt/test_mapping_server.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from unittest.mock import patch, MagicMock 3 | 4 | # https://stackoverflow.com/questions/8658043/how-to-mock-an-import 5 | import sys 6 | sys.modules['cbor'] = MagicMock() 7 | 8 | import numpy as np 9 | 10 | from subt.mapping_server import create_map 11 | 12 | 13 | class MappingServerTest(unittest.TestCase): 14 | 15 | def test_empty_map(self): 16 | m = create_map(np.zeros(shape=(1, 0, 3), dtype=np.float32)) 17 | self.assertEqual(m['data'], b'') 18 | 19 | 20 | # vim: expandtab sw=4 ts=4 21 | -------------------------------------------------------------------------------- /subt/test_marsupial.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from unittest.mock import MagicMock, call 3 | 4 | from subt.marsupial import Marsupial 5 | from osgar.lib import quaternion 6 | 7 | class MarsupialTest(unittest.TestCase): 8 | 9 | def test_detach(self): 10 | bus = bus=MagicMock() 11 | robot = Marsupial(bus=bus, config={'release_at':10}) 12 | robot.on_sim_time_sec(3) 13 | bus.publish.assert_not_called() 14 | robot.on_sim_time_sec(14) 15 | bus.publish.assert_called() 16 | bus.publish.assert_has_calls([call('detach', [])]) 17 | bus.publish.reset_mock() 18 | robot.on_sim_time_sec(15) 19 | bus.publish.assert_not_called() 20 | 21 | def test_robot_name(self): 22 | bus = bus=MagicMock() 23 | robot = Marsupial(bus=bus, config={}) 24 | self.assertIsNone(robot.release_at) 25 | robot_name = b'A10W100L' 26 | robot.on_robot_name(robot_name) 27 | self.assertEqual(robot.release_at, 10) 28 | 29 | # vim: expandtab sw=4 ts=4 30 | -------------------------------------------------------------------------------- /subt/test_octomap.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from unittest.mock import MagicMock 3 | import os 4 | 5 | import cv2 6 | import numpy as np 7 | 8 | from subt.octomap import Octomap, data2maplevel, frontiers 9 | 10 | 11 | class OctomapTest(unittest.TestCase): 12 | 13 | def test_map(self): 14 | with open(os.path.join(os.path.dirname(__file__), 'test_data', 'freyja-octomap.bin'), 'rb') as f: 15 | data = f.read() 16 | self.assertEqual(len(data), 57278) 17 | img = data2maplevel(data, level=2) 18 | cv2.imwrite('octo.png', img) 19 | 20 | def test_frontiers(self): 21 | # no frontiers in totally unknown world 22 | img = np.zeros((1024, 1024, 1), dtype=np.uint8) 23 | __, path = frontiers(img, start=(512, 512, 0)) 24 | self.assertIsNone(path) 25 | 26 | # vim: expandtab sw=4 ts=4 27 | 28 | -------------------------------------------------------------------------------- /subt/test_points2scan.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from unittest.mock import MagicMock 3 | import math 4 | 5 | import numpy as np 6 | 7 | from subt.points2scan import PointsToScan 8 | 9 | 10 | class PointsToScanTest(unittest.TestCase): 11 | 12 | def test_numpy(self): 13 | bus = MagicMock() 14 | conv = PointsToScan(bus=bus, config={}) 15 | 16 | data = np.zeros((16, 1800, 3), dtype=np.float32) 17 | conv.on_points(data) 18 | bus.publish.assert_called() 19 | 20 | # vim: expandtab sw=4 ts=4 21 | 22 | -------------------------------------------------------------------------------- /subt/test_teambase.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import unittest 3 | from unittest.mock import MagicMock, patch, call 4 | 5 | from osgar.bus import Bus 6 | from subt.teambase import Teambase 7 | 8 | 9 | class TeambaseTest(unittest.TestCase): 10 | 11 | def test_finish_time(self): 12 | tb = Teambase(bus=MagicMock(), config={'robot_name':'T42'}) 13 | self.assertEqual(tb.finish_time, 42) 14 | 15 | def test_on_robot_xyz(self): 16 | tb = Teambase(bus=MagicMock(), config={'robot_name':'T300'}) 17 | self.assertEqual(tb.robot_positions, {}) 18 | data = ['A0F150L', [11896, 7018, -11886]] 19 | tb.on_robot_xyz(data) 20 | self.assertEqual(tb.robot_positions, {'A0F150L': [11896, 7018, -11886]}) 21 | 22 | # vim: expandtab sw=4 ts=4 23 | -------------------------------------------------------------------------------- /subt/test_twistwrap.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import math 3 | import unittest 4 | from unittest.mock import MagicMock 5 | 6 | from osgar.bus import Bus 7 | from subt.twistwrap import TwistWrap 8 | 9 | 10 | class TwistWrapTest(unittest.TestCase): 11 | 12 | def test_usage(self): 13 | logger = MagicMock() 14 | bus = Bus(logger) 15 | logger.write = MagicMock(return_value=datetime.timedelta(microseconds=9721)) 16 | c = TwistWrap(bus=bus.handle('twister'), config={}) 17 | tester = bus.handle('tester') 18 | tester.register('desired_speed') 19 | bus.connect('tester.desired_speed', 'twister.desired_speed') 20 | bus.connect('twister.cmd_vel', 'tester.cmd_vel') 21 | c.start() 22 | tester.publish('desired_speed', [1000, 9000]) 23 | c.request_stop() 24 | c.join() 25 | self.assertEqual(tester.listen()[2], [[1.0, 0.0, 0.0], [0.0, 0.0, math.radians(90)]]) 26 | 27 | # vim: expandtab sw=4 ts=4 28 | -------------------------------------------------------------------------------- /subt/test_wifisignal.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from unittest.mock import MagicMock, patch 3 | from time import sleep 4 | 5 | from subt.wifisignal import WifiSignal 6 | 7 | 8 | class WifiSignalTest(unittest.TestCase): 9 | 10 | def test_usage(self): 11 | with patch('subt.wifisignal.wifi_scan') as p: 12 | bus = MagicMock() 13 | ws = WifiSignal(config={}, bus=bus) 14 | bus.is_alive = MagicMock(return_value=True) 15 | ws.start() 16 | sleep(0.1) 17 | bus.is_alive = MagicMock(return_value=False) 18 | ws.join() 19 | 20 | # vim: expandtab sw=4 ts=4 21 | 22 | -------------------------------------------------------------------------------- /subt/tools/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from osgar.lib import create_load_tests 4 | load_tests = create_load_tests(__file__) 5 | -------------------------------------------------------------------------------- /subt/tools/allsync.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import subprocess 4 | from pathlib import Path 5 | 6 | from blessings import Terminal 7 | 8 | 9 | def main(): 10 | 11 | all_robots = { 12 | "k2": "root@10.0.0.21:/home/robot/git/osgar/logs/", 13 | "skiddy": "owner@10.0.0.30:/home/owner/Develop/osgar/sync/", 14 | } 15 | 16 | import argparse 17 | parser = argparse.ArgumentParser(description='rsync logs from robots') 18 | parser.add_argument('robots', nargs='*', choices=list(all_robots.keys()) + [[]], default=[]) 19 | args = parser.parse_args() 20 | 21 | if args.robots == []: 22 | robots = all_robots 23 | else: 24 | robots = {k: all_robots[k] for k in args.robots} 25 | 26 | home = str(Path.home()) 27 | t = Terminal() 28 | try: 29 | while True: 30 | for robot, logs in robots.items(): 31 | print(t.bold(f"Syncing {robot}:")) 32 | print(t.dim, end="", flush=True) 33 | a = subprocess.call(["rsync", "-v", "--append", "--progress", "--recursive", f"{logs}", f"{home}/logs/{robot}"]) 34 | print(t.normal, end="", flush=True) 35 | if a == 0: 36 | print(t.green("OK")) 37 | else: 38 | print(t.red("Failed")) 39 | print() 40 | except KeyboardInterrupt: 41 | print(t.normal, flush=True) 42 | 43 | 44 | if __name__ == "__main__": 45 | main() 46 | -------------------------------------------------------------------------------- /subt/tools/avi2jpg.py: -------------------------------------------------------------------------------- 1 | """ 2 | extract JPEG images from AVI video 3 | usage: 4 | python3 avi2jpg.py 5 | """ 6 | import os.path 7 | 8 | import cv2 9 | 10 | 11 | def avi2jpg(filename, out_dir, start_index=0, end_index=None, show=True): 12 | cap = cv2.VideoCapture(filename) 13 | index = -1 14 | while(cap.isOpened()): 15 | ret, frame = cap.read() 16 | if frame is None: 17 | break 18 | index += 1 19 | if index < start_index: 20 | continue 21 | if end_index is not None and index >= end_index: 22 | break 23 | 24 | out_name = os.path.join(out_dir, 'img_%04d.jpg' % index) 25 | cv2.imwrite(out_name, frame) 26 | if show: 27 | cv2.imshow('image', frame) 28 | if cv2.waitKey(50) == 27: 29 | break 30 | 31 | return index 32 | 33 | 34 | if __name__ == "__main__": 35 | import sys 36 | if len(sys.argv) < 3: 37 | print(__doc__) 38 | sys.exit(-1) 39 | 40 | print(avi2jpg(sys.argv[1], sys.argv[2])) 41 | 42 | # vim: expandtab sw=4 ts=4 43 | -------------------------------------------------------------------------------- /subt/tools/eduroview.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from osgar.tools import lidarview 3 | 4 | if __name__ == "__main__": 5 | args = [ 6 | "--pose2d", "app.pose2d", 7 | "--lidar", "lidar.scan", 8 | "--camera", "camera.raw", 9 | "--keyframes", "detector.artf" 10 | ] + sys.argv[1:] 11 | lidarview.main(args, "eduro") 12 | -------------------------------------------------------------------------------- /subt/tools/kloubakview.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from osgar.tools import lidarview 3 | 4 | if __name__ == "__main__": 5 | args = [ 6 | "--pose3d", "from_jetson_front.pose3d", 7 | "--lidar", "fromros.scan360", 8 | "--deg","360", 9 | "--camera", "camera.raw", 10 | "--camera2", "camera_back.raw", 11 | "--keyframes", "from_jetson_rear.localized_artf", 12 | "--joint", "kloubak.joint_angle", 13 | ] + sys.argv[1:] 14 | lidarview.main(args, "kloubak") 15 | -------------------------------------------------------------------------------- /subt/tools/mariaview.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from osgar.tools import lidarview 3 | 4 | if __name__ == "__main__": 5 | args = [ 6 | "--pose2d", "app.pose2d", 7 | "--lidar", "rosmsg.scan", 8 | "--camera", "rosmsg.image", 9 | "--camera2", "rosmsg.depth", 10 | ] + sys.argv[1:] 11 | lidarview.main(args, "maria") 12 | 13 | -------------------------------------------------------------------------------- /subt/tools/mobosview.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from osgar.tools import lidarview 3 | 4 | if __name__ == "__main__": 5 | args = [ 6 | "--pose2d", "app.pose2d", 7 | "--lidar", "rosmsg.scan", 8 | "--camera", "rosmsg.image", 9 | "--camera2", "rosmsg.depth", 10 | ] + sys.argv[1:] 11 | lidarview.main(args, "mobos") 12 | 13 | -------------------------------------------------------------------------------- /subt/tools/startfile.py: -------------------------------------------------------------------------------- 1 | import os 2 | import os.path 3 | import subprocess 4 | import sys 5 | 6 | if sys.platform[:3] == "win": 7 | 8 | def main(filepath): 9 | normpath = os.path.normpath(filepath) 10 | os.startfile(normpath) 11 | 12 | else: 13 | 14 | def main(filepath): 15 | subprocess.Popen(['xdg-open', filepath], close_fds=True, start_new_session=True) 16 | 17 | 18 | if __name__ == "__main__": 19 | main(sys.argv[1]) 20 | -------------------------------------------------------------------------------- /subt/twistwrap.py: -------------------------------------------------------------------------------- 1 | """ 2 | Wrapper of desired speed for ROS Twist 3 | """ 4 | import math 5 | 6 | from osgar.node import Node 7 | 8 | 9 | class TwistWrap(Node): 10 | def __init__(self, config, bus): 11 | super().__init__(config, bus) 12 | bus.register("cmd_vel") 13 | 14 | def on_desired_speed(self, data): 15 | linear = [data[0]/1000, 0.0, 0.0] 16 | angular = [0.0, 0.0, math.radians(data[1]/100.0)] 17 | self.publish('cmd_vel', [linear, angular]) 18 | 19 | # vim: expandtab sw=4 ts=4 20 | -------------------------------------------------------------------------------- /subt/wifisignal.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | 3 | from osgar.node import Node 4 | 5 | 6 | def wifi_scan(interface): 7 | scanning_cmd = 'sudo iwlist '+interface+' scanning' 8 | with subprocess.Popen(scanning_cmd, shell=True, 9 | stdout=subprocess.PIPE) as cmd: 10 | wifiList = [] 11 | for line in cmd.stdout: 12 | if 'Quality' in str(line): 13 | signalStrength = int(str(line).split("=")[2].split('dBm')[0]) 14 | elif 'ESSID' in str(line): 15 | essid = str(line).split('"')[1] 16 | wifiList.append([essid,signalStrength]) 17 | return wifiList 18 | 19 | 20 | class WifiSignal(Node): 21 | def __init__(self, config, bus): 22 | super().__init__(config, bus) 23 | bus.register('wifiscan') 24 | self.sleep_time = config.get('sleep', 1.0) 25 | self.interface = config.get('interface', 'wlan0') 26 | # TODO ssid 27 | # search SSID 28 | 29 | def run(self): 30 | while self.is_bus_alive(): 31 | wifi_list = wifi_scan(self.interface) 32 | now = self.publish("wifiscan", wifi_list) 33 | self.sleep(self.sleep_time) 34 | 35 | 36 | if __name__ == "__main__": 37 | import time 38 | while True: 39 | result = wifi_scan("wlan0") 40 | print(result) 41 | time.sleep(1) 42 | 43 | # vim: expandtab sw=4 ts=4 44 | 45 | -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | if __name__ == "__main__": 4 | import logging 5 | logging.root.level = logging.CRITICAL 6 | import unittest 7 | import unittest.loader 8 | testLoader = unittest.loader.TestLoader() 9 | from pathlib import Path 10 | top_level_dir = Path(__file__).parent 11 | testLoader._top_level_dir = top_level_dir 12 | unittest.main(module=None, testLoader=testLoader) 13 | --------------------------------------------------------------------------------