Repository: HKUST-Aerial-Robotics/spatiotemporal_semantic_corridor
Branch: master
Commit: e7c5d0989abe
Files: 20
Total size: 142.1 KB
Directory structure:
gitextract_76jbbvj5/
├── readme.md
└── ssc_planner/
├── CMakeLists.txt
├── inc/
│ └── ssc_planner/
│ ├── map_adapter.h
│ ├── map_interface.h
│ ├── ssc_map.h
│ ├── ssc_map_utils.h
│ ├── ssc_planner.h
│ ├── ssc_server_ros.h
│ └── ssc_visualizer.h
├── launch/
│ ├── test_ssc_smm.launch
│ └── test_ssc_with_pubg.launch
├── package.xml
├── rviz/
│ └── ssc_config.rviz
└── src/
├── ssc_planner/
│ ├── map_adapter.cc
│ ├── ssc_map.cc
│ ├── ssc_planner.cc
│ ├── ssc_server_ros.cc
│ └── ssc_visualizer.cc
├── test_ssc_planner_with_smm.cc
└── test_ssc_with_pubg.cc
================================================
FILE CONTENTS
================================================
================================================
FILE: readme.md
================================================
# Spatio-temporal Semantic Corridor
## 0. News
**21 Sept. 2020:** The whole dependencies and a playable demo can be found in: **https://github.com/HKUST-Aerial-Robotics/EPSILON**
**31 August 2019:** The code for the ssc planner is available online!
**3 July 2019:** Our paper is available online!
* **Safe Trajectory Generation for Complex Urban Environments Using Spatio-temporal Semantic Corridor**, Wenchao Ding, Lu Zhang, Jing Chen and Shaojie Shen [IEEE Xplore](https://ieeexplore.ieee.org/document/8740885). *W. Ding and L. Zhang contributed equally to this project.*
```
@article{ding2019safe,
title={Safe Trajectory Generation for Complex Urban Environments Using Spatio-temporal Semantic Corridor},
author={Ding, Wenchao and Zhang, Lu and Chen, Jing and Shen, Shaojie},
journal={IEEE Robotics and Automation Letters},
year={2019},
publisher={IEEE}
}
```
**What Is Next:** The code for the dependencies of this planner is comming soon!
## 1. Introduction
This is the project page for the paper **''Safe Trajectory Generation for Complex Urban Environments Using Spatio-temporal Semantic Corridor''** which is published at IEEE Robotics and Automation Letters (RA-L).
This project contains (**already released**):
* ssc_map: maintainer for the semantic elements in the spatio-temporal domain.
* ssc_planner: planner for generating the semantic corridor in the spatio-temporal domain and optimizing safe and dynamically feasible trajectories.
* ssc_server_ros: ros server which manages the replanning.
* ssc_visualizer: visualizing the elements both in the spatio-temporal domain (in a separate rviz window) and in the global coordinate.
The dependencies of this project includes (**comming soon**):
* `common` package: an integration of various mathematical tools such as polynomial, spline, primitive, lane, trajectory, state, optimization solvers, etc. It provides many easy-to-use interfaces for mathematical modeling.
* `phy_simulator` package: a configurable multi-agent simulator. It provides ground truth information and listens planner feedbacks.
* `semantic_map_manager` package: map with semantic information for vehicle local planning. Each agent is capable of rendering its local planning map based on its configuration.
* `vehicle_model` package: basic vehicle models and controllers.
* `vehicle_msgs` package: ros communication messages and corresponding encoder and decoders.
* `playgrounds` package: test cases/configurations/scenarios stored in json format.
* `behavior_planner` package: mpdm behavior planner for on-road driving. It can provide a local reference lane based on navigation information and behavior decision.
* `forward_simulator` package: forward simulation
* `motion_predictor` package: surrounding vehicle motion prediction.
* `route_planner` package: road-level route planner, a simple version.
The dependencies will be released in another repo: **https://github.com/HKUST-Aerial-Robotics/HDJI_planning_core**.
The overall structure is as follows:

**Videos:**
## 2. Prerequisites
## 3. Build
## 4. Usage
## 5. Demos
================================================
FILE: ssc_planner/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 2.8)
project(ssc_planner)
set(CMAKE_VERBOSE_MAKEFILE "true")
set(CMAKE_BUILD_TYPE "Release")
set(CMAKE_CXX_FLAGS "-std=c++11 -march=native -g")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -Wall")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -Wall")
find_package(catkin REQUIRED COMPONENTS
roscpp
visualization_msgs
sensor_msgs)
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
find_package(OpenMP)
if (OPENMP_FOUND)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
endif()
find_package(common REQUIRED)
find_package(semantic_map_manager REQUIRED)
find_package(behavior_planner REQUIRED)
find_package(pubg_planner REQUIRED)
#only for debugging purpose
find_package(onlane_motion_planner REQUIRED)
#if this catkin packge's header is used by other packages, use catkin_package to
#declare the include directories of this package.
catkin_package(
# INCLUDE_DIRS include
)
include_directories(
inc
${catkin_INCLUDE_DIRS}
${common_INCLUDE_DIRS}
${semantic_map_manager_INCLUDE_DIRS}
${behavior_planner_INCLUDE_DIRS}
${pubg_planner_INCLUDE_DIRS}
${onlane_motion_planner_INCLUDE_DIRS}
)
add_library(ssc_planner_lib STATIC
src/ssc_planner/ssc_planner.cc
src/ssc_planner/ssc_map.cc
src/ssc_planner/map_adapter.cc
)
target_link_libraries(ssc_planner_lib
${common_LIBRARIES}
semantic_map_manager
)
add_library(ssc_server_ros STATIC
src/ssc_planner/ssc_server_ros.cc
src/ssc_planner/ssc_visualizer.cc
)
target_link_libraries(ssc_server_ros
ssc_planner_lib
semantic_map_ros
)
add_executable(test_ssc_planner_with_smm
src/test_ssc_planner_with_smm.cc
)
target_link_libraries(test_ssc_planner_with_smm
${catkin_LIBRARIES}
ssc_server_ros
behavior_planner_ros
onlane_server_ros
)
add_executable(test_ssc_with_pubg
src/test_ssc_with_pubg.cc
)
target_link_libraries(test_ssc_with_pubg
${catkin_LIBRARIES}
ssc_server_ros
pubg_planner_ros
onlane_server_ros
)
#install the hearder files so that other packages can include.
#install(DIRECTORY include/${PROJECT_NAME}/
# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
# DESTINATION ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_INCLUDE_DESTINATION}/
# FILES_MATCHING PATTERN "*.h"
# PATTERN ".svn" EXCLUDE
#)
================================================
FILE: ssc_planner/inc/ssc_planner/map_adapter.h
================================================
/**
* @file map_adapter.h
* @author HKUST Aerial Robotics Group
* @brief map adapter (inherits map interface) for ssc planner
* @version 0.1
* @date 2019-02
* @copyright Copyright (c) 2019
*/
#ifndef _UTIL_SSC_PLANNER_INC_SSC_PLANNER_MAP_ADAPTER_H__
#define _UTIL_SSC_PLANNER_INC_SSC_PLANNER_MAP_ADAPTER_H__
#include "common/basics/semantics.h"
#include "ssc_planner/map_interface.h"
#include "semantic_map_manager/semantic_map_manager.h"
namespace planning {
class SscPlannerAdapter : public SscPlannerMapItf {
public:
using IntegratedMap = semantic_map_manager::SemanticMapManager;
bool IsValid() override;
ErrorType GetEgoVehicle(Vehicle* vehicle) override;
ErrorType GetEgoState(State* state) override;
ErrorType GetEgoReferenceLane(Lane* lane) override;
ErrorType GetLocalNavigationLane(Lane* lane) override;
ErrorType GetLaneByLaneId(const int lane_id, Lane* lane) override;
ErrorType GetSemanticVehicleSet(
SemanticVehicleSet* semantic_vehicle_set) override;
ErrorType GetObstacleMap(GridMap2D* grid_map) override;
ErrorType CheckIfCollision(const common::VehicleParam& vehicle_param,
const State& state, bool* res) override;
ErrorType GetForwardTrajectories(
std::vector* behaviors,
vec_E>* trajs) override;
ErrorType GetEgoDiscretBehavior(LateralBehavior* lat_behavior) override;
ErrorType GetForwardTrajectories(
std::vector* behaviors,
vec_E>* trajs,
vec_E>>* sur_trajs)
override;
ErrorType GetObstacleGrids(
std::set>* obs_grids) override;
ErrorType GetSpeedLimit(vec_E* speed_limit_list) override;
ErrorType GetTrafficLight(
vec_E* traffic_light_list) override;
ErrorType set_map(std::shared_ptr map);
private:
std::shared_ptr map_;
bool is_valid_ = false;
};
} // namespace planning
#endif
================================================
FILE: ssc_planner/inc/ssc_planner/map_interface.h
================================================
/**
* @file map_interface.h
* @author HKUST Aerial Robotics Group
* @brief map interface for ssc planner
* @version 0.1
* @date 2019-02
* @copyright Copyright (c) 2019
*/
#ifndef _UTIL_SSC_PLANNER_INC_SSC_PLANNER_MAP_INTERFACE_H__
#define _UTIL_SSC_PLANNER_INC_SSC_PLANNER_MAP_INTERFACE_H__
#include
#include
#include "common/basics/basics.h"
#include "common/basics/semantics.h"
#include "common/lane/lane.h"
#include "common/state/state.h"
namespace planning {
class SscPlannerMapItf {
public:
using ObstacleMapType = uint8_t;
using State = common::State;
using Lane = common::Lane;
using Vehicle = common::Vehicle;
using LateralBehavior = common::LateralBehavior;
using Behavior = common::SemanticBehavior;
using SemanticVehicleSet = common::SemanticVehicleSet;
using GridMap2D = common::GridMapND;
virtual bool IsValid() = 0;
virtual ErrorType GetEgoVehicle(Vehicle* vehicle) = 0;
virtual ErrorType GetEgoState(State* state) = 0;
virtual ErrorType GetEgoReferenceLane(Lane* lane) = 0;
virtual ErrorType GetLocalNavigationLane(Lane* lane) = 0;
virtual ErrorType GetLaneByLaneId(const int lane_id, Lane* lane) = 0;
virtual ErrorType GetSemanticVehicleSet(
SemanticVehicleSet* semantic_vehicle_set) = 0;
virtual ErrorType GetObstacleMap(GridMap2D* grid_map) = 0;
virtual ErrorType CheckIfCollision(const common::VehicleParam& vehicle_param,
const State& state, bool* res) = 0;
virtual ErrorType GetForwardTrajectories(
std::vector* behaviors,
vec_E>* trajs) = 0;
virtual ErrorType GetForwardTrajectories(
std::vector* behaviors,
vec_E>* trajs,
vec_E>>* sur_trajs) = 0;
virtual ErrorType GetEgoDiscretBehavior(
LateralBehavior* lat_behavior) = 0;
virtual ErrorType GetObstacleGrids(
std::set>* obs_grids) = 0;
virtual ErrorType GetSpeedLimit(
vec_E* speed_limit_list) = 0;
virtual ErrorType GetTrafficLight(
vec_E* traffic_light_list) = 0;
};
} // namespace planning
#endif // _UTIL_SSC_PLANNER_INC_SSC_PLANNER_MAP_INTERFACE_H__
================================================
FILE: ssc_planner/inc/ssc_planner/ssc_map.h
================================================
/**
* @file ssc_map.h
* @author HKUST Aerial Robotics Group
* @brief maintain the spatial temporal map for the planner
* @version 0.1
* @date 2019-02
* @copyright Copyright (c) 2019
*/
#ifndef _UTIL_SSC_PLANNER_INC_SSC_MAP_H_
#define _UTIL_SSC_PLANNER_INC_SSC_MAP_H_
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "common/basics/semantics.h"
#include "common/state/state.h"
namespace planning {
using ObstacleMapType = uint8_t;
using SscMapDataType = uint8_t;
class SscMap {
public:
using State = common::State;
using Lane = common::Lane;
using SemanticVehicleSet = common::SemanticVehicleSet;
using GridMap3D = common::GridMapND;
struct Config {
std::array map_size = {{1000, 100, 51}}; // s, d, t
std::array map_resolution = {{0.25, 0.2, 0.15}}; // m, m, s
std::array axis_name = {{"s", "d", "t"}};
decimal_t s_back_len = 0.0;
decimal_t kMaxLongitudinalVel = 30.0;
decimal_t kMinLongitudinalVel = 0.0;
decimal_t kMaxLateralVel = 2.0;
decimal_t kMaxLongitudinalAcc = 2.0;
decimal_t kMaxLongitudinalDecel = -3.0; // Avg. driver max
decimal_t kMaxLateralAcc = 2.0;
decimal_t kMaxLateralDecel = -2.0;
};
SscMap() {}
SscMap(const Config &config);
~SscMap() {}
GridMap3D *p_3d_grid() const { return p_3d_grid_; }
GridMap3D *p_3d_inflated_grid() const { return p_3d_inflated_grid_; }
Config config() const { return config_; }
vec_E driving_corridor_vec() const {
return driving_corridor_vec_;
}
vec_E>> final_cubes_list()
const {
return final_cubes_list_;
};
std::vector> semantic_voxel_set() const {
return semantic_voxel_set_;
}
std::vector if_corridor_valid() const { return if_corridor_valid_; }
void set_start_time(const decimal_t &t) { start_time_ = t; }
void set_desired_fs(const common::FrenetState &fs) { desired_fs_ = fs; }
void set_semantic_cube_set(
const std::vector> &in) {
semantic_cube_set_ = in;
}
void set_speed_limit_list(const vec_E &in) {
speed_limit_list_ = in;
}
void set_traffic_light_list(const vec_E &in) {
traffic_light_list_ = in;
}
ErrorType ConstructSscMap(
const std::unordered_map>
&sur_vehicle_trajs_fs,
const vec_E &obstacle_grids);
ErrorType InflateObstacleGrid(const common::VehicleParam ¶m);
ErrorType ConstructCorridorsUsingInitialTrajectories(
GridMap3D *p_grid, const vec_E> &trajs);
ErrorType ConstructCorridorUsingInitialTrajectoryWithAssignedBehavior(
GridMap3D *p_grid, const vec_E &trajs);
ErrorType GetDtUsingTimeStamp(const decimal_t &time_stamp,
decimal_t *dt) const;
ErrorType ClearDrivingCorridor();
ErrorType GetFinalGlobalMetricCubesList();
private:
bool CheckIfCubeIsFree(GridMap3D *p_grid,
const common::AxisAlignedsCubeNd &cube) const;
bool CheckIfPlaneIsFreeOnXAxis(GridMap3D *p_grid,
const common::AxisAlignedsCubeNd &cube,
const int &z) const;
bool CheckIfPlaneIsFreeOnYAxis(GridMap3D *p_grid,
const common::AxisAlignedsCubeNd &cube,
const int &z) const;
bool CheckIfPlaneIsFreeOnZAxis(GridMap3D *p_grid,
const common::AxisAlignedsCubeNd &cube,
const int &z) const;
bool CheckIfCubeContainsSeed(const common::AxisAlignedsCubeNd &cube_a,
const Vec3i &seed) const;
bool CheckIfIntersectWithSemanticVoxels(
const common::AxisAlignedsCubeNd &cube,
std::unordered_map> *inters_on_sem_voxels,
std::unordered_map> *inters_on_cube) const;
bool CheckIfIntersectionsIgnorable(
const std::unordered_map> &intersections) const;
ErrorType GetSemanticVoxelSet(GridMap3D *p_grid);
ErrorType GetInitialCubeUsingSeed(const vec_E &seeds, const int &i,
common::AxisAlignedsCubeNd *cube);
ErrorType GetInitialCubeUsingSeed(
const Vec3i &seed_0, const Vec3i &seed_1,
common::AxisAlignedsCubeNd *cube) const;
ErrorType GetTimeCoveredCubeIndices(
const common::DrivingCorridor3D *p_corridor, const int &start_id,
const int &dir, const int &t_trans, std::vector *idx_list) const;
ErrorType CorridorRelaxation(GridMap3D *p_grid,
common::DrivingCorridor3D *p_corridor);
ErrorType FillSemanticInfoInCorridor(GridMap3D *p_grid,
common::DrivingCorridor3D *p_corridor);
ErrorType InflateCubeIn3dGrid(GridMap3D *p_grid,
const std::array &dir_disabled,
const std::array &dir_step,
common::AxisAlignedsCubeNd *cube);
ErrorType GetInflationDirections(const bool &if_inter_with_sv,
const bool &if_first_cube,
const Vec3i &seed_0, const Vec3i &seed_1,
std::array *dirs_disabled);
bool InflateCubeOnXPosAxis(GridMap3D *p_grid, const int &n_step,
const bool &skip_semantic_cube,
common::AxisAlignedsCubeNd *cube);
bool InflateCubeOnXNegAxis(GridMap3D *p_grid, const int &n_step,
const bool &skip_semantic_cube,
common::AxisAlignedsCubeNd *cube);
bool InflateCubeOnYPosAxis(GridMap3D *p_grid, const int &n_step,
const bool &skip_semantic_cube,
common::AxisAlignedsCubeNd *cube);
bool InflateCubeOnYNegAxis(GridMap3D *p_grid, const int &n_step,
const bool &skip_semantic_cube,
common::AxisAlignedsCubeNd *cube);
bool InflateCubeOnZPosAxis(GridMap3D *p_grid, const int &n_step,
const bool &skip_semantic_cube,
common::AxisAlignedsCubeNd *cube);
bool InflateCubeOnZNegAxis(GridMap3D *p_grid, const int &n_step,
const bool &skip_semantic_cube,
common::AxisAlignedsCubeNd *cube);
ErrorType FillStaticPart(const vec_E &obs_grid_fs);
ErrorType FillDynamicPart(
const std::unordered_map>
&sur_vehicle_trajs_fs);
ErrorType FillMapWithFsVehicleTraj(const vec_E traj);
common::GridMapND *p_3d_grid_;
common::GridMapND *p_3d_inflated_grid_;
std::unordered_map> inters_for_sem_voxels_;
std::unordered_map> inters_for_cube_;
Config config_;
decimal_t start_time_;
common::FrenetState desired_fs_;
bool map_valid_ = false;
std::vector> semantic_cube_set_;
std::vector> semantic_voxel_set_;
vec_E driving_corridor_vec_;
std::vector if_corridor_valid_;
vec_E>> final_cubes_list_;
// Traffic signal
vec_E speed_limit_list_;
vec_E traffic_light_list_;
};
} // namespace planning
#endif // _UTIL_SSC_PLANNER_INC_SSC_MAP_H_
================================================
FILE: ssc_planner/inc/ssc_planner/ssc_map_utils.h
================================================
/**
* @file ssc_map_utils.h
* @author HKUST Aerial Robotics Group
* @brief utils for map maintenance
* @version 0.1
* @date 2019-02
* @copyright Copyright (c) 2019
*/
#ifndef _UTIL_SSC_PLANNER_INC_SSC_MAP_UTILS_H__
#define _UTIL_SSC_PLANNER_INC_SSC_MAP_UTILS_H__
#include "ssc_planner/ssc_map.h"
#include "common/basics/basics.h"
#include "common/basics/semantics.h"
#include "common/lane/lane.h"
#include "common/state/frenet_state.h"
#include "common/state/state.h"
#include "common/state/state_transformer.h"
namespace planning {
class SscMapUtils {
public:
static ErrorType RetVehicleVerticesUsingState(
const common::State& state, const common::VehicleParam& param,
vec_E* vertices) {
decimal_t angle = state.angle;
decimal_t x = state.vec_position(0);
decimal_t y = state.vec_position(1);
decimal_t cos_theta = cos(angle);
decimal_t sin_theta = sin(angle);
decimal_t c_x = x + param.d_cr() * cos_theta;
decimal_t c_y = y + param.d_cr() * sin_theta;
decimal_t d_wx = param.width() / 2 * sin_theta;
decimal_t d_wy = param.width() / 2 * cos_theta;
decimal_t d_lx = param.length() / 2 * cos_theta;
decimal_t d_ly = param.length() / 2 * sin_theta;
// Counterclockwise from left-front vertex
vertices->push_back(Vec2f(c_x - d_wx + d_lx, c_y + d_wy + d_ly));
// vertices->push_back(Vec2f(c_x - d_wx, c_y + d_wy));
vertices->push_back(Vec2f(c_x - d_wx - d_lx, c_y - d_ly + d_wy));
// vertices->push_back(Vec2f(c_x - d_lx, c_y - d_ly));
vertices->push_back(Vec2f(c_x + d_wx - d_lx, c_y - d_wy - d_ly));
// vertices->push_back(Vec2f(c_x + d_wx, c_y - d_wy));
vertices->push_back(Vec2f(c_x + d_wx + d_lx, c_y + d_ly - d_wy));
// vertices->push_back(Vec2f(c_x + d_lx, c_y + d_ly));
return kSuccess;
}
}; // SscMapUtils
} // namespace planning
#endif // _UTIL_SSC_PLANNER_INC_SSC_MAP_UTILS_H__
================================================
FILE: ssc_planner/inc/ssc_planner/ssc_planner.h
================================================
/**
* @file ssc_planner.h
* @author HKUST Aerial Robotics Group
* @brief planner using spatio-temporal corridor
* @version 0.1
* @date 2019-02
* @copyright Copyright (c) 2019
*/
#ifndef _UTIL_SSC_PLANNER_INC_SSC_SEARCH_H_
#define _UTIL_SSC_PLANNER_INC_SSC_SEARCH_H_
#include
#include
#include
#include
#include "common/basics/basics.h"
#include "common/interface/planner.h"
#include "common/lane/lane.h"
#include "common/spline/spline_generator.h"
#include "common/state/frenet_state.h"
#include "common/state/state.h"
#include "common/state/state_transformer.h"
#include "common/trajectory/trajectory.h"
#include "ssc_planner/map_interface.h"
#include "ssc_planner/ssc_map.h"
namespace planning {
class SscPlanner : public Planner {
public:
using ObstacleMapType = uint8_t;
using SscMapDataType = uint8_t;
using Lane = common::Lane;
using State = common::State;
using Vehicle = common::Vehicle;
using LateralBehavior = common::LateralBehavior;
using FrenetState = common::FrenetState;
using Trajectory = common::Trajectory;
using SemanticVehicleSet = common::SemanticVehicleSet;
using GridMap2D = common::GridMapND;
typedef common::BezierSpline<5, 2> BezierSpline;
struct Config {
decimal_t kSampleBezierStep{0.05};
decimal_t kMaxCurvature{0.3};
decimal_t kMaxTangentAcceleration{2.0};
decimal_t kMaxNormalAcceleration{2.0};
decimal_t kMaxTangentDeceleration{2.0};
decimal_t kMaxVelocity{28.0};
};
SscPlanner();
SscPlanner(const Config& cfg);
/**
* @brief setters
*/
ErrorType set_map_interface(SscPlannerMapItf* map_itf);
ErrorType set_init_state(const State& state);
/**
* @brief getters
*/
SscMap* p_ssc_map() const { return p_ssc_map_; }
FrenetState ego_frenet_state() const { return ego_frenet_state_; }
Vehicle ego_vehicle() const { return ego_vehicle_; }
vec_E> forward_trajs() const { return forward_trajs_; }
vec_E qp_trajs() const { return qp_trajs_; }
decimal_t time_origin() const { return time_origin_; }
std::unordered_map> sur_vehicle_trajs_fs()
const {
return sur_vehicle_trajs_fs_;
}
vec_E> forward_trajs_fs() const {
return forward_trajs_fs_;
}
vec_E ego_vehicle_contour_fs() const {
return fs_ego_vehicle_.vertices;
}
Trajectory trajectory() const { return trajectory_; }
/**
* @brief Initialize the planner with config path
*/
std::string Name() override;
/**
* @brief Initialize the planner with config path
*/
ErrorType Init(const std::string config) override;
/**
* @brief Run one planning round with given states
*/
ErrorType RunOnce() override;
private:
ErrorType CorridorFeasibilityCheck(
const vec_E>& cubes);
/**
* @brief transform all the states in a batch
*/
ErrorType StateTransformForInputData();
ErrorType RunQpOptimization();
/**
* @brief transform all the states using openmp
*/
ErrorType StateTransformUsingOpenMp(const vec_E& global_state_vec,
const vec_E& global_point_vec,
vec_E* frenet_state_vec,
vec_E* fs_point_vec) const;
ErrorType StateTransformSingleThread(const vec_E& global_state_vec,
const vec_E& global_point_vec,
vec_E* frenet_state_vec,
vec_E* fs_point_vec) const;
ErrorType GetBezierSplineWithCurrentBehavior(
const vec_E& trajs,
const std::vector& behaviors,
BezierSpline* bezier_spline);
ErrorType BezierToTrajectory(const BezierSpline& bezier_spline,
Trajectory* traj);
ErrorType GetSemanticCubeList(
const vec_E& speed_limit,
const vec_E& traffic_light,
std::vector>* cubes);
Vehicle ego_vehicle_;
LateralBehavior ego_behavior_;
FrenetState ego_frenet_state_;
Lane nav_lane_local_;
decimal_t time_origin_{0.0};
State init_state_;
bool has_init_state_ = false;
GridMap2D grid_map_;
std::set> obstacle_grids_;
SemanticVehicleSet semantic_vehicle_set_;
vec_E> forward_trajs_;
std::vector forward_behaviors_;
vec_E>> surround_forward_trajs_;
vec_E obstacle_grids_fs_;
// Initial solution for optimization
common::FsVehicle fs_ego_vehicle_;
vec_E> forward_trajs_fs_;
std::unordered_map> sur_vehicle_trajs_fs_;
vec_E>>
surround_forward_trajs_fs_;
vec_E qp_trajs_;
std::vector valid_behaviors_;
Trajectory trajectory_;
common::StateTransformer stf_;
// Map
SscPlannerMapItf* map_itf_;
bool map_valid_ = false;
SscMap* p_ssc_map_;
std::pair last_lane_s_;
bool has_last_state_s_ = false;
decimal_t global_s_offset_ = 0.0;
TicToc timer_;
Config config_;
};
} // namespace planning
#endif
================================================
FILE: ssc_planner/inc/ssc_planner/ssc_server_ros.h
================================================
/**
* @file ssc_server_ros.h
* @author HKUST Aerial Robotics Group
* @brief planner server
* @version 0.1
* @date 2019-02
* @copyright Copyright (c) 2019
*/
#ifndef _UTIL_SSC_PLANNER_INC_SSC_SERVER_ROS_H_
#define _UTIL_SSC_PLANNER_INC_SSC_SERVER_ROS_H_
#include "ros/ros.h"
#include
#include
#include
#include "semantic_map_manager/semantic_map_manager.h"
#include "semantic_map_manager/visualizer.h"
#include "ssc_planner/map_adapter.h"
#include "ssc_planner/ssc_planner.h"
#include "ssc_planner/ssc_visualizer.h"
#include "common/basics/colormap.h"
#include "common/basics/tic_toc.h"
#include "common/lane/lane.h"
#include "common/lane/lane_generator.h"
#include "common/trajectory/trajectory.h"
#include "common/visualization/common_visualization_util.h"
#include "moodycamel/atomicops.h"
#include "moodycamel/readerwriterqueue.h"
#include
#include "tf/tf.h"
#include "tf/transform_datatypes.h"
#include "vehicle_msgs/ControlSignal.h"
#include "vehicle_msgs/encoder.h"
#include "visualization_msgs/Marker.h"
#include "visualization_msgs/MarkerArray.h"
namespace planning {
class SscPlannerServer {
public:
using SemanticMapManager = semantic_map_manager::SemanticMapManager;
struct Config {
int kInputBufferSize{100};
};
SscPlannerServer(ros::NodeHandle nh, int ego_id);
SscPlannerServer(ros::NodeHandle nh, double work_rate, int ego_id);
void PushSemanticMap(const SemanticMapManager &smm);
void Init();
void Start();
private:
void PlanCycleCallback();
void JoyCallback(const sensor_msgs::Joy::ConstPtr &msg);
void Replan();
void PublishData();
void MainThread();
Config config_;
bool is_replan_on_ = false;
bool is_map_updated_ = false;
common::Trajectory executing_traj_;
common::Trajectory next_traj_;
SscPlanner planner_;
SscPlannerAdapter map_adapter_;
TicToc time_profile_tool_;
decimal_t global_init_stamp_{0.0};
common::VehicleControlSignal joy_ctrl_signal;
// ros related
ros::NodeHandle nh_;
decimal_t work_rate_ = 20.0;
int ego_id_;
ros::Publisher ctrl_signal_pub_;
ros::Publisher map_marker_pub_;
ros::Publisher executing_traj_vis_pub_;
ros::Subscriber joy_sub_;
// input buffer
moodycamel::ReaderWriterQueue *p_input_smm_buff_;
SemanticMapManager last_smm_;
semantic_map_manager::Visualizer *p_smm_vis_{nullptr};
SscVisualizer *p_ssc_vis_{nullptr};
int last_trajmk_cnt_{0};
};
} // namespace planning
#endif // _UTIL_SSC_PLANNER_INC_SSC_SERVER_ROS_H__
================================================
FILE: ssc_planner/inc/ssc_planner/ssc_visualizer.h
================================================
/**
* @file ssc_visualizer.h
* @author HKUST Aerial Robotics Group
* @brief visualizer for the planner
* @version 0.1
* @date 2019-02
* @copyright Copyright (c) 2019
*/
#ifndef _UTIL_SSC_PLANNER_INC_VISUALIZER_H_
#define _UTIL_SSC_PLANNER_INC_VISUALIZER_H_
#include
#include
#include
#include
#include
#include
#include "common/basics/basics.h"
#include "common/basics/semantics.h"
#include "common/primitive/frenet_primitive.h"
#include "common/state/frenet_state.h"
#include "common/state/state.h"
#include "common/visualization/common_visualization_util.h"
#include "ssc_planner/ssc_planner.h"
namespace planning {
class SscVisualizer {
public:
SscVisualizer(ros::NodeHandle nh, int node_id);
~SscVisualizer() {}
void VisualizeDataWithStamp(const ros::Time &stamp,
const SscPlanner &planner);
private:
void VisualizeSscMap(const ros::Time &stamp, const SscMap *p_ssc_map);
void VisualizeEgoVehicleInSscSpace(const ros::Time &stamp,
const vec_E &ego_vehicle_contour_fs,
const decimal_t &ego_time);
void VisualizeForwardTrajectoriesInSscSpace(
const ros::Time &stamp, const vec_E> &trajs,
const SscMap *p_ssc_map);
void VisualizeQpTrajs(const ros::Time &stamp,
const vec_E> &trajs);
void VisualizeSurroundingVehicleTrajInSscSpace(
const ros::Time &stamp,
const std::unordered_map> &trajs,
const SscMap *p_ssc_map);
void VisualizeCorridorsInSscSpace(
const ros::Time &stamp,
const vec_E corridor_vec,
const SscMap *p_ssc_map);
void VisualizeSemanticVoxelSet(
const ros::Time &stamp,
const std::vector> &voxel_set,
const SscMap *p_ssc_map);
int last_traj_list_marker_cnt_ = 0;
int last_surrounding_vehicle_marker_cnt_ = 0;
ros::NodeHandle nh_;
int node_id_;
decimal_t start_time_;
ros::Publisher ssc_map_pub_;
ros::Publisher ego_vehicle_pub_;
ros::Publisher forward_trajs_pub_;
ros::Publisher sur_vehicle_trajs_pub_;
ros::Publisher corridor_pub_;
ros::Publisher qp_pub_;
ros::Publisher semantic_voxel_set_pub_;
int last_corridor_mk_cnt = 0;
int last_qp_traj_mk_cnt = 0;
int last_sur_vehicle_traj_mk_cnt = 0;
int last_forward_traj_mk_cnt = 0;
decimal_t marker_lifetime_{0.05};
}; // SscVisualizer
} // namespace planning
#endif // _UTIL_SSC_PLANNER_INC_VISUALIZER_H_
================================================
FILE: ssc_planner/launch/test_ssc_smm.launch
================================================
================================================
FILE: ssc_planner/launch/test_ssc_with_pubg.launch
================================================
================================================
FILE: ssc_planner/package.xml
================================================
ssc_planner
0.0.0
ssc_planner
HKUST_UAV_GROUP
TODO
catkin
roscpp
rospy
common
semantic_map_manager
roscpp
rospy
common
semantic_map_manager
================================================
FILE: ssc_planner/rviz/ssc_config.rviz
================================================
Panels:
- Class: rviz/Displays
Help Height: 78
Name: Displays
Property Tree Widget:
Expanded:
- /Global Options1
- /Corridor1
- /Corridor1/Namespaces1
- /QpTraj1
Splitter Ratio: 0.5
Tree Height: 1203
- Class: rviz/Selection
Name: Selection
- Class: rviz/Tool Properties
Expanded:
- /2D Pose Estimate1
- /2D Nav Goal1
- /Publish Point1
Name: Tool Properties
Splitter Ratio: 0.588679016
- Class: rviz/Views
Expanded:
- /Current View1
Name: Views
Splitter Ratio: 0.5
- Class: rviz/Time
Experimental: false
Name: Time
SyncMode: 0
SyncSource: ""
Visualization Manager:
Class: ""
Displays:
- Alpha: 0.5
Cell Size: 5
Class: rviz/Grid
Color: 160; 160; 164
Enabled: false
Line Style:
Line Width: 0.0299999993
Value: Lines
Name: Grid
Normal Cell Count: 0
Offset:
X: 0
Y: 0
Z: 0
Plane: XY
Plane Cell Count: 10
Reference Frame:
Value: false
- Class: rviz/MarkerArray
Enabled: true
Marker Topic: /vis/agent_0/ssc/map_vis
Name: 3DGridMap
Namespaces:
"": true
Queue Size: 100
Value: true
- Class: rviz/Marker
Enabled: true
Marker Topic: /vis/agent_0/ssc/ego_fs_vis
Name: EgoVehicle
Namespaces:
"": true
Queue Size: 100
Value: true
- Class: rviz/MarkerArray
Enabled: true
Marker Topic: /vis/agent_0/ssc/sur_vehicle_trajs_vis
Name: SurVehicle
Namespaces:
"": true
Queue Size: 100
Value: true
- Class: rviz/MarkerArray
Enabled: true
Marker Topic: /vis/agent_0/ssc/forward_trajs_vis
Name: ForwardTrajs
Namespaces:
"": true
Queue Size: 100
Value: true
- Class: rviz/MarkerArray
Enabled: false
Marker Topic: /vis/agent_0/ssc/corridor_vis
Name: Corridor
Namespaces:
{}
Queue Size: 100
Value: false
- Class: rviz/MarkerArray
Enabled: false
Marker Topic: /vis/agent_0/ssc/qp_vis
Name: QpTraj
Namespaces:
{}
Queue Size: 100
Value: false
- Class: rviz/MarkerArray
Enabled: true
Marker Topic: /vis/agent_0/ssc/semantic_voxel_vis
Name: SemCube
Namespaces:
"": true
Queue Size: 100
Value: true
Enabled: true
Global Options:
Background Color: 255; 255; 255
Default Light: true
Fixed Frame: ssc_map
Frame Rate: 30
Name: root
Tools:
- Class: rviz/Interact
Hide Inactive Objects: true
- Class: rviz/MoveCamera
- Class: rviz/Select
- Class: rviz/FocusCamera
- Class: rviz/Measure
- Class: rviz/SetInitialPose
Topic: /initialpose
- Class: rviz/SetGoal
Topic: /move_base_simple/goal
- Class: rviz/PublishPoint
Single click: true
Topic: /clicked_point
Value: true
Views:
Current:
Class: rviz/Orbit
Distance: 68.6894684
Enable Stereo Rendering:
Stereo Eye Separation: 0.0599999987
Stereo Focal Distance: 1
Swap Stereo Eyes: false
Value: false
Focal Point:
X: 31.3054199
Y: 3.30344224
Z: 1.9960165
Focal Shape Fixed Size: false
Focal Shape Size: 0.0500000007
Invert Z Axis: false
Name: Current View
Near Clip Distance: 0.00999999978
Pitch: 0.44979769
Target Frame: ssc_map
Value: Orbit (rviz)
Yaw: 2.38508368
Saved: ~
Window Geometry:
Displays:
collapsed: true
Height: 877
Hide Left Dock: true
Hide Right Dock: true
QMainWindow State: 000000ff00000000fd00000004000000000000016a00000542fc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000006100fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073000000002800000542000000d700fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f00000327fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073000000002800000327000000ad00fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000004b00000003efc0100000002fb0000000800540069006d00650000000000000004b00000030000fffffffb0000000800540069006d00650100000000000004500000000000000000000005a00000032700000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
Selection:
collapsed: false
Time:
collapsed: false
Tool Properties:
collapsed: false
Views:
collapsed: true
Width: 1440
X: 2370
Y: 54
================================================
FILE: ssc_planner/src/ssc_planner/map_adapter.cc
================================================
/**
* @file map_adpater.cc
* @author HKUST Aerial Robotics Group
* @brief implementation for map adapter
* @version 0.1
* @date 2019-02
* @copyright Copyright (c) 2019
*/
#include "ssc_planner/map_adapter.h"
namespace planning {
ErrorType SscPlannerAdapter::set_map(std::shared_ptr map) {
map_ = map; // maintain a snapshop of the environment
is_valid_ = true;
return kSuccess;
}
bool SscPlannerAdapter::IsValid() { return is_valid_; }
ErrorType SscPlannerAdapter::GetEgoVehicle(Vehicle* vehicle) {
if (!is_valid_) return kWrongStatus;
*vehicle = map_->ego_vehicle();
return kSuccess;
}
ErrorType SscPlannerAdapter::GetEgoState(State* state) {
if (!is_valid_) return kWrongStatus;
*state = map_->ego_vehicle().state();
return kSuccess;
}
ErrorType SscPlannerAdapter::GetLocalNavigationLane(Lane* lane) {
if (!is_valid_) return kWrongStatus;
auto ref_lane = map_->ego_behavior().navi_lane_local;
if (!ref_lane.IsValid()) {
printf("[GetEgoReferenceLane]No reference lane existing.\n");
return kWrongStatus;
}
*lane = ref_lane;
return kSuccess;
}
ErrorType SscPlannerAdapter::GetForwardTrajectories(
std::vector* behaviors,
vec_E>* trajs) {
if (!is_valid_) return kWrongStatus;
if (map_->ego_behavior().forward_behaviors.size() < 1) return kWrongStatus;
*behaviors = map_->ego_behavior().forward_behaviors;
*trajs = map_->ego_behavior().forward_trajs;
return kSuccess;
}
ErrorType SscPlannerAdapter::GetForwardTrajectories(
std::vector* behaviors,
vec_E>* trajs,
vec_E>>* sur_trajs) {
if (!is_valid_) return kWrongStatus;
if (map_->ego_behavior().forward_behaviors.size() < 1) return kWrongStatus;
*behaviors = map_->ego_behavior().forward_behaviors;
*trajs = map_->ego_behavior().forward_trajs;
*sur_trajs = map_->ego_behavior().surround_trajs;
return kSuccess;
}
ErrorType SscPlannerAdapter::GetEgoDiscretBehavior(
LateralBehavior* lat_behavior) {
if (!is_valid_) return kWrongStatus;
if (map_->ego_behavior().lat_behavior == common::LateralBehavior::kUndefined)
return kWrongStatus;
*lat_behavior = map_->ego_behavior().lat_behavior;
return kSuccess;
}
ErrorType SscPlannerAdapter::GetLaneByLaneId(const int lane_id, Lane* lane) {
if (!is_valid_) return kWrongStatus;
auto semantic_lane_set = map_->semantic_lane_set();
auto it = semantic_lane_set.semantic_lanes.find(lane_id);
if (it == semantic_lane_set.semantic_lanes.end()) {
return kWrongStatus;
} else {
*lane = it->second.lane;
}
return kSuccess;
}
ErrorType SscPlannerAdapter::GetEgoReferenceLane(Lane* lane) {
if (!is_valid_) return kWrongStatus;
auto ref_lane = map_->ego_behavior().ref_lane;
// auto ref_lane = map_->ego_behavior().navi_lane_local;
if (!ref_lane.IsValid()) {
printf("[GetEgoReferenceLane]No reference lane existing.\n");
return kWrongStatus;
}
*lane = ref_lane;
return kSuccess;
}
ErrorType SscPlannerAdapter::GetSemanticVehicleSet(
SemanticVehicleSet* semantic_vehicle_set) {
if (!is_valid_) return kWrongStatus;
*semantic_vehicle_set = map_->s_semantic_vehicles();
return kSuccess;
}
ErrorType SscPlannerAdapter::GetObstacleMap(GridMap2D* grid_map) {
if (!is_valid_) return kWrongStatus;
*grid_map = map_->obstacle_map();
return kSuccess;
}
ErrorType SscPlannerAdapter::CheckIfCollision(
const common::VehicleParam& vehicle_param, const State& state, bool* res) {
if (!is_valid_) return kWrongStatus;
map_->CheckCollisionUsingStateAndVehicleParam(vehicle_param, state, res);
return kSuccess;
}
ErrorType SscPlannerAdapter::GetObstacleGrids(
std::set>* obs_grids) {
if (!is_valid_) return kWrongStatus;
*obs_grids = map_->obstacle_grids();
return kSuccess;
}
ErrorType SscPlannerAdapter::GetSpeedLimit(
vec_E* speed_limit_list) {
if (!is_valid_) return kWrongStatus;
*speed_limit_list = map_->RetTrafficInfoSpeedLimit();
return kSuccess;
}
ErrorType SscPlannerAdapter::GetTrafficLight(
vec_E* traffic_light_list) {
if (!is_valid_) return kWrongStatus;
*traffic_light_list = map_->RetTrafficInfoTrafficLight();
return kSuccess;
}
} // namespace planning
================================================
FILE: ssc_planner/src/ssc_planner/ssc_map.cc
================================================
/**
* @file ssc_map.cc
* @author HKUST Aerial Robotics Group
* @brief implementation for ssc map
* @version 0.1
* @date 2019-02
* @copyright Copyright (c) 2019
*/
#include "ssc_planner/ssc_map.h"
#include "ssc_planner/ssc_map_utils.h"
namespace planning {
SscMap::SscMap(const SscMap::Config &config) : config_(config) {
p_3d_grid_ = new common::GridMapND(
config_.map_size, config_.map_resolution, config_.axis_name);
p_3d_inflated_grid_ = new common::GridMapND(
config_.map_size, config_.map_resolution, config_.axis_name);
std::array map_origin = {};
map_origin[0] = 0; //-1 * config_.s_back_len; // s
map_origin[1] =
-1 * config_.map_size[1] * config_.map_resolution[1] / 2; // d
map_origin[2] = 0.0; // t
p_3d_grid_->set_origin(map_origin);
p_3d_inflated_grid_->set_origin(map_origin);
}
ErrorType SscMap::GetDtUsingTimeStamp(const decimal_t &time_stamp,
decimal_t *dt) const {
*dt = time_stamp - start_time_;
return kSuccess;
}
ErrorType SscMap::GetInitialCubeUsingSeed(
const Vec3i &seed_0, const Vec3i &seed_1,
common::AxisAlignedsCubeNd *cube) const {
std::vector lb(3);
std::vector ub(3);
lb[0] = std::min(seed_0(0), seed_1(0));
lb[1] = std::min(seed_0(1), seed_1(1));
lb[2] = std::min(seed_0(2), seed_1(2));
ub[0] = std::max(seed_0(0), seed_1(0));
ub[1] = std::max(seed_0(1), seed_1(1));
ub[2] = std::max(seed_0(2), seed_1(2));
*cube = common::AxisAlignedsCubeNd(ub, lb);
return kSuccess;
}
ErrorType SscMap::ConstructSscMap(
const std::unordered_map>
&sur_vehicle_trajs_fs,
const vec_E &obstacle_grids) {
p_3d_grid_->clear_data();
p_3d_inflated_grid_->clear_data();
FillStaticPart(obstacle_grids);
FillDynamicPart(sur_vehicle_trajs_fs);
return kSuccess;
}
ErrorType SscMap::GetInflationDirections(const bool &if_inter_with_sv,
const bool &if_first_cube,
const Vec3i &seed_0,
const Vec3i &seed_1,
std::array *dirs_disabled) {
bool z_neg_disabled = true;
if (if_first_cube) {
z_neg_disabled = false;
}
if (if_inter_with_sv) {
for (auto it = inters_for_sem_voxels_.begin();
it != inters_for_sem_voxels_.end(); ++it) {
for (int j = 0; j < 6; ++j) {
if (it->second[j]) {
int dim = j / 2;
if (seed_0[dim] < seed_1[dim]) {
(*dirs_disabled)[2 * dim] = false;
(*dirs_disabled)[2 * dim + 1] = true;
} else {
(*dirs_disabled)[2 * dim] = true;
(*dirs_disabled)[2 * dim + 1] = false;
}
}
}
}
(*dirs_disabled)[4] = false;
(*dirs_disabled)[5] = z_neg_disabled;
} else {
(*dirs_disabled)[0] = false;
(*dirs_disabled)[1] = false;
(*dirs_disabled)[2] = false;
(*dirs_disabled)[3] = false;
(*dirs_disabled)[4] = false;
(*dirs_disabled)[5] = z_neg_disabled;
}
return kSuccess;
}
ErrorType SscMap::ConstructCorridorsUsingInitialTrajectories(
GridMap3D *p_grid, const vec_E> &trajs) {
GetSemanticVoxelSet(p_grid);
driving_corridor_vec_.clear();
int trajs_num = trajs.size();
if (trajs_num < 1) return kWrongStatus;
// ~ Stage I: Get seeds
vec_E> seeds_vec;
for (int i = 0; i < trajs_num; ++i) {
common::DrivingCorridor3D driving_corridor;
vec_E traj_seeds;
int num_states = static_cast(trajs[i].size());
if (num_states > 1) {
bool first_seed_determined = false;
for (int k = 0; k < num_states; ++k) {
std::array p_w = {};
if (!first_seed_determined) {
decimal_t s_0 = desired_fs_.vec_s[0];
decimal_t d_0 = desired_fs_.vec_ds[0];
decimal_t t_0 = 0.0;
std::array p_w_0 = {s_0, d_0, t_0};
auto round_p_0 = p_grid->GetRoundedPosUsingGlobalPosition(p_w_0);
decimal_t s_1 = trajs[i][k + 1].frenet_state.vec_s[0];
decimal_t d_1 = trajs[i][k + 1].frenet_state.vec_ds[0];
decimal_t t_1 = trajs[i][k + 1].frenet_state.time_stamp - start_time_;
std::array p_w_1 = {s_1, d_1, t_1};
auto round_p_1 = p_grid->GetRoundedPosUsingGlobalPosition(p_w_1);
if (round_p_1[2] <= 0) {
continue;
}
if ((round_p_0[1] >= d_0 && d_0 >= round_p_1[1]) ||
(round_p_1[1] >= d_0 && d_0 >= round_p_0[1])) {
p_w = p_w_0;
} else {
if (std::min(round_p_0[1], round_p_1[1]) > d_0) {
p_w = p_w_0;
p_w[1] -= p_grid->dims_resolution(1);
} else if (std::max(round_p_0[1], round_p_1[1]) < d_0) {
p_w = p_w_0;
p_w[1] += p_grid->dims_resolution(1);
} else {
assert(false);
}
}
first_seed_determined = true;
} else {
decimal_t s = trajs[i][k].frenet_state.vec_s[0];
decimal_t d = trajs[i][k].frenet_state.vec_ds[0];
decimal_t t = trajs[i][k].frenet_state.time_stamp - start_time_;
p_w = {s, d, t};
}
auto coord = p_grid->GetCoordUsingGlobalPosition(p_w);
// * remove the states out of range
if (!p_grid->CheckCoordInRange(coord)) {
continue;
}
traj_seeds.push_back(Vec3i(coord[0], coord[1], coord[2]));
}
}
if (!traj_seeds.empty()) {
seeds_vec.push_back(traj_seeds);
}
}
// ~ Stage II: Inflate cubes
TicToc timer;
for (const auto &seeds : seeds_vec) {
common::DrivingCorridor3D driving_corridor;
bool is_valid = true;
auto seeds_num = static_cast(seeds.size());
if (seeds_num < 2) {
driving_corridor.is_valid = false;
driving_corridor_vec_.push_back(driving_corridor);
is_valid = false;
continue;
}
for (int i = 0; i < seeds_num; ++i) {
if (i == 0) {
common::AxisAlignedsCubeNd cube;
GetInitialCubeUsingSeed(seeds[i], seeds[i + 1], &cube);
if (!CheckIfCubeIsFree(p_grid, cube)) {
printf("[error] Init cube is not free, seed id = %d\n", i);
common::DrivingCube driving_cube;
driving_cube.cube = cube;
driving_cube.seeds.push_back(seeds[i]);
driving_cube.seeds.push_back(seeds[i + 1]);
driving_corridor.cubes.push_back(driving_cube);
driving_corridor.is_valid = false;
driving_corridor_vec_.push_back(driving_corridor);
is_valid = false;
break;
}
inters_for_sem_voxels_.clear();
inters_for_cube_.clear();
bool if_inter_with_sv = CheckIfIntersectWithSemanticVoxels(
cube, &inters_for_sem_voxels_, &inters_for_cube_);
// std::array dirs_disabled = {
// {false, false, false, false, false, false}};
std::array dirs_disabled;
GetInflationDirections(if_inter_with_sv, true, seeds[i], seeds[i + 1],
&dirs_disabled);
InflateCubeIn3dGrid(p_grid, dirs_disabled, {{20, 1, 10, 10, 1, 1}},
&cube);
common::DrivingCube driving_cube;
driving_cube.cube = cube;
driving_cube.seeds.push_back(seeds[i]);
driving_corridor.cubes.push_back(driving_cube);
} else {
if (CheckIfCubeContainsSeed(driving_corridor.cubes.back().cube,
seeds[i])) {
driving_corridor.cubes.back().seeds.push_back(seeds[i]);
continue;
} else {
if (driving_corridor.cubes.back().seeds.size() <= 1) {
printf("[Deprecated branch]\n");
printf("[SscQP]find one bad corridor break at %d with %d seeds.\n",
i, static_cast(seeds.size()));
driving_corridor.is_valid = false;
driving_corridor.cubes.back().seeds.push_back(seeds[i]);
driving_corridor_vec_.push_back(driving_corridor);
is_valid = false;
break;
} else {
// ~ Get the last seed in cube
Vec3i seed_r = driving_corridor.cubes.back().seeds.back();
driving_corridor.cubes.back().seeds.pop_back();
// ~ Cut cube on time axis
driving_corridor.cubes.back().cube.pos_ub[2] = seed_r(2);
i = i - 1;
common::AxisAlignedsCubeNd cube;
GetInitialCubeUsingSeed(seeds[i], seeds[i + 1], &cube);
if (!CheckIfCubeIsFree(p_grid, cube)) {
printf("[error] Init cube is not free, seed id = %d\n", i);
common::DrivingCube driving_cube;
driving_cube.cube = cube;
driving_cube.seeds.push_back(seeds[i]);
driving_cube.seeds.push_back(seeds[i + 1]);
driving_corridor.cubes.push_back(driving_cube);
driving_corridor.is_valid = false;
driving_corridor_vec_.push_back(driving_corridor);
is_valid = false;
break;
}
inters_for_sem_voxels_.clear();
inters_for_cube_.clear();
bool if_inter_with_sv = CheckIfIntersectWithSemanticVoxels(
cube, &inters_for_sem_voxels_, &inters_for_cube_);
if (if_inter_with_sv) {
for (const auto &inter : inters_for_sem_voxels_) {
printf("[Inflation]Ignored: %d -- %d, %d, %d, %d, %d, %d\n",
inter.first, inter.second[0], inter.second[1],
inter.second[2], inter.second[3], inter.second[4],
inter.second[5]);
}
}
// std::array dirs_disabled = {
// {false, false, false, false, false, true}};
std::array dirs_disabled;
GetInflationDirections(if_inter_with_sv, false, seeds[i],
seeds[i + 1], &dirs_disabled);
InflateCubeIn3dGrid(p_grid, dirs_disabled, {{20, 1, 10, 10, 1, 1}},
&cube);
common::DrivingCube driving_cube;
driving_cube.cube = cube;
driving_cube.seeds.push_back(seeds[i]);
driving_corridor.cubes.push_back(driving_cube);
}
}
}
}
if (is_valid) {
CorridorRelaxation(p_grid, &driving_corridor);
FillSemanticInfoInCorridor(p_grid, &driving_corridor);
driving_corridor.cubes.back().cube.pos_ub[2] = seeds.back()(2);
driving_corridor.is_valid = true;
driving_corridor_vec_.push_back(driving_corridor);
}
}
GetFinalGlobalMetricCubesList();
printf("[Corr] Inflate cube cost = %lf\n", timer.toc());
std::cout << "[Corr] trajs.size() = " << trajs.size() << std::endl;
return kSuccess;
}
ErrorType SscMap::ClearDrivingCorridor() {
driving_corridor_vec_.clear();
return kSuccess;
}
ErrorType SscMap::ConstructCorridorUsingInitialTrajectoryWithAssignedBehavior(
GridMap3D *p_grid, const vec_E &trajs) {
GetSemanticVoxelSet(p_grid);
// ~ Stage I: Get seeds
vec_E traj_seeds;
int num_states = static_cast(trajs.size());
if (num_states > 1) {
bool first_seed_determined = false;
for (int k = 0; k < num_states; ++k) {
std::array p_w = {};
if (!first_seed_determined) {
decimal_t s_0 = desired_fs_.vec_s[0];
decimal_t d_0 = desired_fs_.vec_ds[0];
decimal_t t_0 = 0.0;
std::array p_w_0 = {s_0, d_0, t_0};
auto round_p_0 = p_grid->GetRoundedPosUsingGlobalPosition(p_w_0);
decimal_t s_1 = trajs[k + 1].frenet_state.vec_s[0];
decimal_t d_1 = trajs[k + 1].frenet_state.vec_ds[0];
decimal_t t_1 = trajs[k + 1].frenet_state.time_stamp - start_time_;
std::array p_w_1 = {s_1, d_1, t_1};
auto round_p_1 = p_grid->GetRoundedPosUsingGlobalPosition(p_w_1);
if (round_p_1[2] <= 0) {
continue;
}
if ((round_p_0[1] >= d_0 && d_0 >= round_p_1[1]) ||
(round_p_1[1] >= d_0 && d_0 >= round_p_0[1])) {
p_w = p_w_0;
} else {
if (std::min(round_p_0[1], round_p_1[1]) > d_0) {
p_w = p_w_0;
p_w[1] -= p_grid->dims_resolution(1);
} else if (std::max(round_p_0[1], round_p_1[1]) < d_0) {
p_w = p_w_0;
p_w[1] += p_grid->dims_resolution(1);
} else {
assert(false);
}
}
// printf("[Seed] p_w = %lf, %lf, %lf\n", p_w[0], p_w[1], p_w[2]);
first_seed_determined = true;
} else {
decimal_t s = trajs[k].frenet_state.vec_s[0];
decimal_t d = trajs[k].frenet_state.vec_ds[0];
decimal_t t = trajs[k].frenet_state.time_stamp - start_time_;
p_w = {s, d, t};
}
auto coord = p_grid->GetCoordUsingGlobalPosition(p_w);
// * remove the states out of range
if (!p_grid->CheckCoordInRange(coord)) {
continue;
}
traj_seeds.push_back(Vec3i(coord[0], coord[1], coord[2]));
}
}
// ~ Stage II: Inflate cubes
common::DrivingCorridor3D driving_corridor;
bool is_valid = true;
auto seed_num = static_cast(traj_seeds.size());
if (seed_num < 2) {
driving_corridor.is_valid = false;
driving_corridor_vec_.push_back(driving_corridor);
is_valid = false;
return kWrongStatus;
}
for (int i = 0; i < seed_num; ++i) {
if (i == 0) {
common::AxisAlignedsCubeNd cube;
GetInitialCubeUsingSeed(traj_seeds[i], traj_seeds[i + 1], &cube);
if (!CheckIfCubeIsFree(p_grid, cube)) {
printf("[error] Init cube is not free, seed id = %d\n", i);
common::DrivingCube driving_cube;
driving_cube.cube = cube;
driving_cube.seeds.push_back(traj_seeds[i]);
driving_cube.seeds.push_back(traj_seeds[i + 1]);
driving_corridor.cubes.push_back(driving_cube);
driving_corridor.is_valid = false;
driving_corridor_vec_.push_back(driving_corridor);
is_valid = false;
break;
}
inters_for_sem_voxels_.clear();
inters_for_cube_.clear();
bool if_inter_with_sv = CheckIfIntersectWithSemanticVoxels(
cube, &inters_for_sem_voxels_, &inters_for_cube_);
// std::array dirs_disabled = {
// {false, false, false, false, false, false}};
std::array dirs_disabled;
GetInflationDirections(if_inter_with_sv, true, traj_seeds[i],
traj_seeds[i + 1], &dirs_disabled);
InflateCubeIn3dGrid(p_grid, dirs_disabled, {{20, 1, 10, 10, 1, 1}},
&cube);
common::DrivingCube driving_cube;
driving_cube.cube = cube;
driving_cube.seeds.push_back(traj_seeds[i]);
driving_corridor.cubes.push_back(driving_cube);
} else {
if (CheckIfCubeContainsSeed(driving_corridor.cubes.back().cube,
traj_seeds[i])) {
driving_corridor.cubes.back().seeds.push_back(traj_seeds[i]);
continue;
} else {
if (driving_corridor.cubes.back().seeds.size() <= 1) {
// ! CHECK: Still need this condition?
printf("[Deprecated branch]\n");
printf("[SscQP]find one bad corridor break at %d with %d seeds.\n", i,
static_cast(traj_seeds.size()));
driving_corridor.is_valid = false;
driving_corridor.cubes.back().seeds.push_back(traj_seeds[i]);
driving_corridor_vec_.push_back(driving_corridor);
is_valid = false;
break;
} else {
// ~ Get the last seed in cube
Vec3i seed_r = driving_corridor.cubes.back().seeds.back();
driving_corridor.cubes.back().seeds.pop_back();
// ~ Cut cube on time axis
driving_corridor.cubes.back().cube.pos_ub[2] = seed_r(2);
i = i - 1;
common::AxisAlignedsCubeNd cube;
GetInitialCubeUsingSeed(traj_seeds[i], traj_seeds[i + 1], &cube);
if (!CheckIfCubeIsFree(p_grid, cube)) {
printf("[error] Init cube is not free, seed id = %d\n", i);
common::DrivingCube driving_cube;
driving_cube.cube = cube;
driving_cube.seeds.push_back(traj_seeds[i]);
driving_cube.seeds.push_back(traj_seeds[i + 1]);
driving_corridor.cubes.push_back(driving_cube);
driving_corridor.is_valid = false;
driving_corridor_vec_.push_back(driving_corridor);
is_valid = false;
break;
}
inters_for_sem_voxels_.clear();
inters_for_cube_.clear();
bool if_inter_with_sv = CheckIfIntersectWithSemanticVoxels(
cube, &inters_for_sem_voxels_, &inters_for_cube_);
if (if_inter_with_sv) {
for (const auto &inter : inters_for_sem_voxels_) {
printf("[Inflation]Ignored: %d -- %d, %d, %d, %d, %d, %d\n",
inter.first, inter.second[0], inter.second[1],
inter.second[2], inter.second[3], inter.second[4],
inter.second[5]);
}
}
// std::array dirs_disabled = {
// {false, false, false, false, false, true}};
std::array dirs_disabled;
GetInflationDirections(if_inter_with_sv, false, traj_seeds[i],
traj_seeds[i + 1], &dirs_disabled);
InflateCubeIn3dGrid(p_grid, dirs_disabled, {{20, 1, 10, 10, 1, 1}},
&cube);
common::DrivingCube driving_cube;
driving_cube.cube = cube;
driving_cube.seeds.push_back(traj_seeds[i]);
driving_corridor.cubes.push_back(driving_cube);
}
}
}
}
if (is_valid) {
CorridorRelaxation(p_grid, &driving_corridor);
FillSemanticInfoInCorridor(p_grid, &driving_corridor);
driving_corridor.cubes.back().cube.pos_ub[2] = traj_seeds.back()(2);
driving_corridor.is_valid = true;
driving_corridor_vec_.push_back(driving_corridor);
}
return kSuccess;
}
ErrorType SscMap::GetTimeCoveredCubeIndices(
const common::DrivingCorridor3D *p_corridor, const int &start_idx,
const int &dir, const int &t_trans, std::vector *idx_list) const {
int dt = 0;
int num_cube = p_corridor->cubes.size();
int idx = start_idx;
while (idx < num_cube && idx >= 0) {
dt += p_corridor->cubes[idx].cube.pos_ub[2] -
p_corridor->cubes[idx].cube.pos_lb[2];
idx_list->push_back(idx);
if (dir == 1) {
++idx;
} else {
--idx;
}
if (dt >= t_trans) {
break;
}
}
return kSuccess;
}
ErrorType SscMap::CorridorRelaxation(GridMap3D *p_grid,
common::DrivingCorridor3D *p_corridor) {
std::array margin = {{50, 10}};
int t_trans = 7;
int num_cube = p_corridor->cubes.size();
for (int i = 0; i < num_cube - 1; ++i) {
if (1) // ~ Enable s direction
{
int cube_0_lb = p_corridor->cubes[i].cube.pos_lb[0];
int cube_0_ub = p_corridor->cubes[i].cube.pos_ub[0];
int cube_1_lb = p_corridor->cubes[i + 1].cube.pos_lb[0];
int cube_1_ub = p_corridor->cubes[i + 1].cube.pos_ub[0];
if (abs(cube_0_ub - cube_1_lb) < margin[0]) {
int room = margin[0] - abs(cube_0_ub - cube_1_lb);
// ~ Upward
std::vector up_idx_list;
GetTimeCoveredCubeIndices(p_corridor, i + 1, 1, t_trans, &up_idx_list);
// ~ Downward
std::vector down_idx_list;
GetTimeCoveredCubeIndices(p_corridor, i, 0, t_trans, &down_idx_list);
for (const auto &idx : up_idx_list) {
InflateCubeOnXNegAxis(p_grid, room, true,
&(p_corridor->cubes[idx].cube));
}
for (const auto &idx : down_idx_list) {
InflateCubeOnXPosAxis(p_grid, room, true,
&(p_corridor->cubes[idx].cube));
}
}
if (abs(cube_0_lb - cube_1_ub) < margin[0]) {
int room = margin[0] - abs(cube_0_lb - cube_1_ub);
// ~ Upward
std::vector up_idx_list;
GetTimeCoveredCubeIndices(p_corridor, i + 1, 1, t_trans, &up_idx_list);
// ~ Downward
std::vector down_idx_list;
GetTimeCoveredCubeIndices(p_corridor, i, 0, t_trans, &down_idx_list);
for (const auto &idx : up_idx_list) {
InflateCubeOnXPosAxis(p_grid, room, true,
&(p_corridor->cubes[idx].cube));
}
for (const auto &idx : down_idx_list) {
InflateCubeOnXNegAxis(p_grid, room, true,
&(p_corridor->cubes[idx].cube));
}
}
}
if (1) // ~ Enable d direction
{
int cube_0_lb = p_corridor->cubes[i].cube.pos_lb[1];
int cube_0_ub = p_corridor->cubes[i].cube.pos_ub[1];
int cube_1_lb = p_corridor->cubes[i + 1].cube.pos_lb[1];
int cube_1_ub = p_corridor->cubes[i + 1].cube.pos_ub[1];
if (abs(cube_0_ub - cube_1_lb) < margin[1]) {
int room = margin[1] - abs(cube_0_ub - cube_1_lb);
// ~ Upward
std::vector up_idx_list;
GetTimeCoveredCubeIndices(p_corridor, i + 1, 1, t_trans, &up_idx_list);
// ~ Downward
std::vector down_idx_list;
GetTimeCoveredCubeIndices(p_corridor, i, 0, t_trans, &down_idx_list);
for (const auto &idx : up_idx_list) {
InflateCubeOnYNegAxis(p_grid, room, true,
&(p_corridor->cubes[idx].cube));
}
for (const auto &idx : down_idx_list) {
InflateCubeOnYPosAxis(p_grid, room, true,
&(p_corridor->cubes[idx].cube));
}
}
if (abs(cube_0_lb - cube_1_ub) < margin[1]) {
int room = margin[1] - abs(cube_0_lb - cube_1_ub);
// ~ Upward
std::vector up_idx_list;
GetTimeCoveredCubeIndices(p_corridor, i + 1, 1, t_trans, &up_idx_list);
// ~ Downward
std::vector down_idx_list;
GetTimeCoveredCubeIndices(p_corridor, i, 0, t_trans, &down_idx_list);
for (const auto idx : up_idx_list) {
InflateCubeOnYPosAxis(p_grid, room, true,
&(p_corridor->cubes[idx].cube));
}
for (const auto idx : down_idx_list) {
InflateCubeOnYNegAxis(p_grid, room, true,
&(p_corridor->cubes[idx].cube));
}
}
}
}
return kSuccess;
}
ErrorType SscMap::FillSemanticInfoInCorridor(
GridMap3D *p_grid, common::DrivingCorridor3D *p_corridor) {
// ~ Use the first seed
int num_cube = p_corridor->cubes.size();
for (int i = 0; i < num_cube; ++i) {
for (int j = 0; j < static_cast(semantic_voxel_set_.size()); ++j) {
if (CheckIfCubeContainsSeed(semantic_voxel_set_[j],
p_corridor->cubes[i].seeds[0])) {
p_corridor->cubes[i].cube.v_lb = semantic_voxel_set_[j].v_lb;
p_corridor->cubes[i].cube.v_ub = semantic_voxel_set_[j].v_ub;
break;
}
}
}
return kSuccess;
}
ErrorType SscMap::InflateObstacleGrid(const common::VehicleParam ¶m) {
decimal_t s_p_inflate_len = param.length() / 2.0 - param.d_cr();
decimal_t s_n_inflate_len = param.length() - s_p_inflate_len;
int num_s_p_inflate_grids =
std::floor(s_p_inflate_len / config_.map_resolution[0]);
int num_s_n_inflate_grids =
std::floor(s_n_inflate_len / config_.map_resolution[0]);
int num_d_inflate_grids =
std::floor((param.width() - 0.5) / 2.0 / config_.map_resolution[1]);
bool is_free = false;
for (int i = 0; i < config_.map_size[0]; ++i) {
for (int j = 0; j < config_.map_size[1]; ++j) {
for (int k = 0; k < config_.map_size[2]; ++k) {
std::array coord = {i, j, k};
p_3d_grid_->CheckIfEqualUsingCoordinate(coord, 0, &is_free);
if (!is_free) {
for (int s = -num_s_n_inflate_grids; s < num_s_p_inflate_grids; s++) {
for (int d = -num_d_inflate_grids; d < num_d_inflate_grids; d++) {
coord = {i + s, j + d, k};
p_3d_inflated_grid_->SetValueUsingCoordinate(coord, 100);
}
}
}
}
}
}
return kSuccess;
}
ErrorType SscMap::InflateCubeIn3dGrid(
GridMap3D *p_grid, const std::array &dir_disabled,
const std::array &dir_step,
common::AxisAlignedsCubeNd *cube) {
bool x_p_finish = dir_disabled[0];
bool x_n_finish = dir_disabled[1];
bool y_p_finish = dir_disabled[2];
bool y_n_finish = dir_disabled[3];
bool z_p_finish = dir_disabled[4];
// bool z_n_finish = dir_disabled[5];
int x_p_step = dir_step[0];
int x_n_step = dir_step[1];
int y_p_step = dir_step[2];
int y_n_step = dir_step[3];
int z_p_step = dir_step[4];
// int z_n_step = dir_step[5];
// int s_idx_ini = cube->pos_lb[0];
// int d_idx_ini = cube->pos_lb[1];
int t_idx_ini = cube->pos_lb[2];
decimal_t t = t_idx_ini * p_grid->dims_resolution(2);
decimal_t a_max = 4.7;
decimal_t a_min = -4.7;
decimal_t s_u = desired_fs_.vec_s[1] * t + 0.5 * a_max * t * t;
decimal_t s_l = desired_fs_.vec_s[1] * t + 0.5 * a_min * t * t;
int s_idx_u, s_idx_l;
p_grid->GetCoordUsingGlobalMetricOnSingleDim(s_u, 0, &s_idx_u);
p_grid->GetCoordUsingGlobalMetricOnSingleDim(s_l, 0, &s_idx_l);
while (!(x_p_finish && x_n_finish && y_p_finish && y_n_finish)) {
if (!x_p_finish)
x_p_finish = InflateCubeOnXPosAxis(p_grid, x_p_step, false, cube);
if (!x_n_finish)
x_n_finish = InflateCubeOnXNegAxis(p_grid, x_n_step, false, cube);
if (!y_p_finish)
y_p_finish = InflateCubeOnYPosAxis(p_grid, y_p_step, false, cube);
if (!y_n_finish)
y_n_finish = InflateCubeOnYNegAxis(p_grid, y_n_step, false, cube);
if (cube->pos_ub[0] > s_idx_u) x_p_finish = true;
if (cube->pos_lb[0] < s_idx_l) x_n_finish = true;
if (cube->pos_lb[0] <
(p_grid->origin()[0] + 17) / config_.map_resolution[0]) {
x_n_finish = true;
}
}
// ~ No need to inflate along z-neg
while (!z_p_finish) {
if (!z_p_finish)
z_p_finish = InflateCubeOnZPosAxis(p_grid, z_p_step, true, cube);
if (cube->pos_ub[2] - cube->pos_lb[2] >= 1) {
z_p_finish = true;
// z_n_finish = true;
}
}
return kSuccess;
}
bool SscMap::InflateCubeOnXPosAxis(GridMap3D *p_grid, const int &n_step,
const bool &skip_semantic_cube,
common::AxisAlignedsCubeNd *cube) {
for (int i = 0; i < n_step; ++i) {
int x = cube->pos_ub[0] + 1;
if (!p_grid->CheckCoordInRangeOnSingleDim(x, 0)) {
return true;
} else {
if (CheckIfPlaneIsFreeOnXAxis(p_grid, *cube, x)) {
// The plane in 3D obstacle grid is free
std::unordered_map> inter_res;
std::unordered_map> inter_cube; // not used
common::AxisAlignedsCubeNd cube_tmp = *cube;
cube_tmp.pos_ub[0] = x;
if (skip_semantic_cube || !CheckIfIntersectWithSemanticVoxels(
cube_tmp, &inter_res, &inter_cube)) {
// Without intersect with semantic voxels
cube->pos_ub[0] = x;
} else {
// Intersect with semantic voxels
if (CheckIfIntersectionsIgnorable(inter_res)) {
// Intersections ignorable
cube->pos_ub[0] = x;
} else {
// Intersections are not ignorable
return true;
}
}
} else {
// The plane in 3D obstacle grid is not free, finish
return true;
}
}
}
return false;
}
bool SscMap::InflateCubeOnXNegAxis(GridMap3D *p_grid, const int &n_step,
const bool &skip_semantic_cube,
common::AxisAlignedsCubeNd *cube) {
for (int i = 0; i < n_step; ++i) {
int x = cube->pos_lb[0] - 1;
if (!p_grid->CheckCoordInRangeOnSingleDim(x, 0)) {
return true;
} else {
if (CheckIfPlaneIsFreeOnXAxis(p_grid, *cube, x)) {
// The plane in 3D obstacle grid is free
std::unordered_map> inter_res;
std::unordered_map> inter_cube; // not used
common::AxisAlignedsCubeNd cube_tmp = *cube;
cube_tmp.pos_lb[0] = x;
if (skip_semantic_cube || !CheckIfIntersectWithSemanticVoxels(
cube_tmp, &inter_res, &inter_cube)) {
// Without intersect with semantic voxels
cube->pos_lb[0] = x;
} else {
// Intersect with semantic voxels
if (CheckIfIntersectionsIgnorable(inter_res)) {
// Intersections ignorable
cube->pos_lb[0] = x;
} else {
// Intersections are not ignorable
return true;
}
}
} else {
return true;
}
}
}
return false;
}
bool SscMap::InflateCubeOnYPosAxis(GridMap3D *p_grid, const int &n_step,
const bool &skip_semantic_cube,
common::AxisAlignedsCubeNd *cube) {
for (int i = 0; i < n_step; ++i) {
int y = cube->pos_ub[1] + 1;
if (!p_grid->CheckCoordInRangeOnSingleDim(y, 1)) {
return true;
} else {
if (CheckIfPlaneIsFreeOnYAxis(p_grid, *cube, y)) {
// The plane in 3D obstacle grid is free
std::unordered_map> inter_res;
std::unordered_map> inter_cube; // not used
common::AxisAlignedsCubeNd cube_tmp = *cube;
cube_tmp.pos_ub[1] = y;
if (skip_semantic_cube || !CheckIfIntersectWithSemanticVoxels(
cube_tmp, &inter_res, &inter_cube)) {
// Without intersect with semantic voxels
cube->pos_ub[1] = y;
} else {
// Intersect with semantic voxels
if (CheckIfIntersectionsIgnorable(inter_res)) {
// Intersections ignorable
cube->pos_ub[1] = y;
} else {
// Intersections are not ignorable
return true;
}
}
} else {
return true;
}
}
}
return false;
}
bool SscMap::InflateCubeOnYNegAxis(GridMap3D *p_grid, const int &n_step,
const bool &skip_semantic_cube,
common::AxisAlignedsCubeNd *cube) {
for (int i = 0; i < n_step; ++i) {
int y = cube->pos_lb[1] - 1;
if (!p_grid->CheckCoordInRangeOnSingleDim(y, 1)) {
return true;
} else {
if (CheckIfPlaneIsFreeOnYAxis(p_grid, *cube, y)) {
// The plane in 3D obstacle grid is free
std::unordered_map> inter_res;
std::unordered_map> inter_cube; // not used
common::AxisAlignedsCubeNd cube_tmp = *cube;
cube_tmp.pos_lb[1] = y;
if (skip_semantic_cube || !CheckIfIntersectWithSemanticVoxels(
cube_tmp, &inter_res, &inter_cube)) {
// Without intersect with semantic voxels
cube->pos_lb[1] = y;
} else {
// Intersect with semantic voxels
if (CheckIfIntersectionsIgnorable(inter_res)) {
// Intersections ignorable
cube->pos_lb[1] = y;
} else {
// Intersections are not ignorable
return true;
}
}
} else {
return true;
}
}
}
return false;
}
bool SscMap::InflateCubeOnZPosAxis(GridMap3D *p_grid, const int &n_step,
const bool &skip_semantic_cube,
common::AxisAlignedsCubeNd *cube) {
for (int i = 0; i < n_step; ++i) {
int z = cube->pos_ub[2] + 1;
if (!p_grid->CheckCoordInRangeOnSingleDim(z, 2)) {
return true;
} else {
if (CheckIfPlaneIsFreeOnZAxis(p_grid, *cube, z)) {
// The plane in 3D obstacle grid is free
std::unordered_map> inter_res;
std::unordered_map> inter_cube; // not used
common::AxisAlignedsCubeNd cube_tmp = *cube;
cube_tmp.pos_ub[2] = z;
if (skip_semantic_cube || !CheckIfIntersectWithSemanticVoxels(
cube_tmp, &inter_res, &inter_cube)) {
// Without intersect with semantic voxels
cube->pos_ub[2] = z;
} else {
// Intersect with semantic voxels
if (CheckIfIntersectionsIgnorable(inter_res)) {
// Intersections ignorable
cube->pos_ub[2] = z;
} else {
// Intersections are not ignorable
return true;
}
}
} else {
return true;
}
}
}
return false;
}
bool SscMap::InflateCubeOnZNegAxis(GridMap3D *p_grid, const int &n_step,
const bool &skip_semantic_cube,
common::AxisAlignedsCubeNd *cube) {
for (int i = 0; i < n_step; ++i) {
int z = cube->pos_lb[2] - 1;
if (!p_grid->CheckCoordInRangeOnSingleDim(z, 2)) {
return true;
} else {
if (CheckIfPlaneIsFreeOnZAxis(p_grid, *cube, z)) {
// The plane in 3D obstacle grid is free
std::unordered_map> inter_res;
std::unordered_map> inter_cube; // not used
common::AxisAlignedsCubeNd cube_tmp = *cube;
cube_tmp.pos_lb[2] = z;
if (skip_semantic_cube || !CheckIfIntersectWithSemanticVoxels(
cube_tmp, &inter_res, &inter_cube)) {
// Without intersect with semantic voxels
cube->pos_lb[2] = z;
} else {
// Intersect with semantic voxels
if (CheckIfIntersectionsIgnorable(inter_res)) {
// Intersections ignorable
cube->pos_lb[2] = z;
} else {
// Intersections are not ignorable
return true;
}
}
} else {
return true;
}
}
}
return false;
}
ErrorType SscMap::GetSemanticVoxelSet(GridMap3D *p_grid) {
// ~ Convert semantic cube (constraints) to voxel coordinate
semantic_voxel_set_.clear();
int cube_num = semantic_cube_set_.size();
for (int i = 0; i < cube_num; ++i) {
std::array p_ub = {{semantic_cube_set_[i].pos_ub[0],
semantic_cube_set_[i].pos_ub[1],
semantic_cube_set_[i].pos_ub[2]}};
auto coord_ub = p_grid->GetCoordUsingGlobalPosition(p_ub);
std::array p_lb = {{semantic_cube_set_[i].pos_lb[0],
semantic_cube_set_[i].pos_lb[1],
semantic_cube_set_[i].pos_lb[2]}};
auto coord_lb = p_grid->GetCoordUsingGlobalPosition(p_lb);
common::AxisAlignedsCubeNd cube(
{coord_ub[0], coord_ub[1], coord_ub[2]},
{coord_lb[0], coord_lb[1], coord_lb[2]});
cube.v_lb = semantic_cube_set_[i].v_lb;
cube.v_ub = semantic_cube_set_[i].v_ub;
cube.a_lb = semantic_cube_set_[i].a_lb;
cube.a_ub = semantic_cube_set_[i].a_ub;
semantic_voxel_set_.push_back(cube);
}
return kSuccess;
}
bool SscMap::CheckIfCubeIsFree(
GridMap3D *p_grid, const common::AxisAlignedsCubeNd &cube) const {
int f0_min = cube.pos_lb[0];
int f0_max = cube.pos_ub[0];
int f1_min = cube.pos_lb[1];
int f1_max = cube.pos_ub[1];
int f2_min = cube.pos_lb[2];
int f2_max = cube.pos_ub[2];
int i, j, k;
std::array coord;
bool is_free;
for (i = f0_min; i <= f0_max; ++i) {
for (j = f1_min; j <= f1_max; ++j) {
for (k = f2_min; k <= f2_max; ++k) {
coord = {i, j, k};
p_grid->CheckIfEqualUsingCoordinate(coord, 0, &is_free);
if (!is_free) {
return false;
}
}
}
}
return true;
}
bool SscMap::CheckIfPlaneIsFreeOnXAxis(
GridMap3D *p_grid, const common::AxisAlignedsCubeNd &cube,
const int &x) const {
int f0_min = cube.pos_lb[1];
int f0_max = cube.pos_ub[1];
int f1_min = cube.pos_lb[2];
int f1_max = cube.pos_ub[2];
int i, j;
std::array coord;
bool is_free;
for (i = f0_min; i <= f0_max; ++i) {
for (j = f1_min; j <= f1_max; ++j) {
coord = {x, i, j};
p_grid->CheckIfEqualUsingCoordinate(coord, 0, &is_free);
if (!is_free) {
return false;
}
}
}
return true;
}
bool SscMap::CheckIfPlaneIsFreeOnYAxis(
GridMap3D *p_grid, const common::AxisAlignedsCubeNd &cube,
const int &y) const {
int f0_min = cube.pos_lb[0];
int f0_max = cube.pos_ub[0];
int f1_min = cube.pos_lb[2];
int f1_max = cube.pos_ub[2];
int i, j;
std::array coord;
bool is_free;
for (i = f0_min; i <= f0_max; ++i) {
for (j = f1_min; j <= f1_max; ++j) {
coord = {i, y, j};
p_grid->CheckIfEqualUsingCoordinate(coord, 0, &is_free);
if (!is_free) {
return false;
}
}
}
return true;
}
bool SscMap::CheckIfPlaneIsFreeOnZAxis(
GridMap3D *p_grid, const common::AxisAlignedsCubeNd &cube,
const int &z) const {
int f0_min = cube.pos_lb[0];
int f0_max = cube.pos_ub[0];
int f1_min = cube.pos_lb[1];
int f1_max = cube.pos_ub[1];
int i, j;
std::array coord;
bool is_free;
for (i = f0_min; i <= f0_max; ++i) {
for (j = f1_min; j <= f1_max; ++j) {
coord = {i, j, z};
p_grid->CheckIfEqualUsingCoordinate(coord, 0, &is_free);
if (!is_free) {
return false;
}
}
}
return true;
}
bool SscMap::CheckIfCubeContainsSeed(
const common::AxisAlignedsCubeNd &cube_a, const Vec3i &seed) const {
for (int i = 0; i < 3; ++i) {
if (cube_a.pos_lb[i] > seed(i) || cube_a.pos_ub[i] < seed(i)) {
return false;
}
}
return true;
}
bool SscMap::CheckIfIntersectWithSemanticVoxels(
const common::AxisAlignedsCubeNd &cube,
std::unordered_map> *inters_on_sem_voxels,
std::unordered_map> *inters_on_cube) const {
// ~ intersections: id -- results
bool if_intersect = false;
int num_semantic_voxels = semantic_voxel_set_.size();
for (int i = 0; i < num_semantic_voxels; ++i) {
std::array inter_dim_a;
std::array inter_dim_b;
if (common::ShapeUtils::CheckIfAxisAlignedCubeNdIntersect(
cube, semantic_voxel_set_[i], &inter_dim_a, &inter_dim_b)) {
inters_on_sem_voxels->insert(
std::pair>(i, inter_dim_b));
inters_on_cube->insert(
std::pair>(i, inter_dim_a));
if_intersect = true;
}
}
return if_intersect;
}
bool SscMap::CheckIfIntersectionsIgnorable(
const std::unordered_map> &inters) const {
for (const auto inter : inters) {
int id = inter.first;
auto it = inters_for_sem_voxels_.find(id);
if (it == inters_for_sem_voxels_.end()) {
return false;
} else {
for (int i = 0; i < 6; ++i) {
if (it->second[i] != inter.second[i]) {
return false;
}
}
}
}
return true;
}
ErrorType SscMap::GetFinalGlobalMetricCubesList() {
final_cubes_list_.clear();
if_corridor_valid_.clear();
for (const auto corridor : driving_corridor_vec_) {
vec_E> cubes;
if (!corridor.is_valid) {
if_corridor_valid_.push_back(0);
} else {
if_corridor_valid_.push_back(1);
for (int k = 0; k < static_cast(corridor.cubes.size()); ++k) {
common::AxisAlignedsCubeNd cube;
decimal_t x_lb, x_ub;
decimal_t y_lb, y_ub;
decimal_t z_lb, z_ub;
p_3d_grid_->GetGlobalMetricUsingCoordOnSingleDim(
corridor.cubes[k].cube.pos_lb[0], 0, &x_lb);
p_3d_grid_->GetGlobalMetricUsingCoordOnSingleDim(
corridor.cubes[k].cube.pos_ub[0], 0, &x_ub);
p_3d_grid_->GetGlobalMetricUsingCoordOnSingleDim(
corridor.cubes[k].cube.pos_lb[1], 1, &y_lb);
p_3d_grid_->GetGlobalMetricUsingCoordOnSingleDim(
corridor.cubes[k].cube.pos_ub[1], 1, &y_ub);
p_3d_grid_->GetGlobalMetricUsingCoordOnSingleDim(
corridor.cubes[k].cube.pos_lb[2], 2, &z_lb);
p_3d_grid_->GetGlobalMetricUsingCoordOnSingleDim(
corridor.cubes[k].cube.pos_ub[2], 2, &z_ub);
cube.pos_lb.push_back(x_lb);
cube.pos_lb.push_back(y_lb);
cube.pos_lb.push_back(z_lb + start_time_);
cube.pos_ub.push_back(x_ub);
cube.pos_ub.push_back(y_ub);
cube.pos_ub.push_back(z_ub + start_time_);
cube.v_lb[0] = config_.kMinLongitudinalVel;
cube.v_ub[0] = corridor.cubes[k].cube.v_ub[0];
cube.a_lb[0] = config_.kMaxLongitudinalDecel;
cube.a_ub[0] = config_.kMaxLongitudinalAcc;
cube.v_lb[1] = -config_.kMaxLateralAcc;
cube.v_ub[1] = config_.kMaxLateralAcc;
cube.a_lb[1] = config_.kMaxLateralDecel;
cube.a_ub[1] = config_.kMaxLateralAcc;
if (k == 0) {
if (y_lb > desired_fs_.vec_ds[0] || y_ub < desired_fs_.vec_ds[0]) {
printf("[Error] error, d = %lf, lb = %lf, ub = %lf\n",
desired_fs_.vec_ds[0], y_lb, y_ub);
assert(false);
}
}
cubes.push_back(cube);
}
}
final_cubes_list_.push_back(cubes);
}
return kSuccess;
}
ErrorType SscMap::FillStaticPart(const vec_E &obs_grid_fs) {
for (int i = 0; i < static_cast(obs_grid_fs.size()); ++i) {
if (obs_grid_fs[i](0) <= 0) {
continue;
}
for (int k = 0; k < config_.map_size[2]; ++k) {
std::array pt = {{obs_grid_fs[i](0), obs_grid_fs[i](1),
(double)k * config_.map_resolution[2]}};
auto coord = p_3d_grid_->GetCoordUsingGlobalPosition(pt);
if (p_3d_grid_->CheckCoordInRange(coord)) {
p_3d_grid_->SetValueUsingCoordinate(coord, 100);
}
}
}
return kSuccess;
}
ErrorType SscMap::FillDynamicPart(
const std::unordered_map>
&sur_vehicle_trajs_fs) {
for (auto it = sur_vehicle_trajs_fs.begin(); it != sur_vehicle_trajs_fs.end();
++it) {
FillMapWithFsVehicleTraj(it->second);
}
return kSuccess;
}
ErrorType SscMap::FillMapWithFsVehicleTraj(
const vec_E traj) {
if (traj.size() == 0) {
printf("[SscMap] Trajectory is empty!");
return kWrongStatus;
}
for (int i = 0; i < static_cast