Vehicle Node#
The ROS 2 package ROS/acres_vehicle has the node vehicle_node: the vehicle program in C++. The node connects the topics of the Polaris to the run-time library. It has no numerical code. The pose, the scan, the inputs and the control step come from the vehicle handle.
In the simulator, the node drives the Polaris of ACRES Core over ROS 2 (Closed Loop with ACRES Core).
| Part | Location |
|---|---|
| Messages to inputs, and the control step | include/acres_vehicle/VehicleProgram.h, src/VehicleProgram.cpp |
| Node, modes, record and commands | src/vehicle_node.cpp |
| Launch files | launch/vehicle.launch.py, launch/sim_drive.launch.py |
| Tests | test/test_vehicle_node.py, test/test_drive_rules.py, test/test_gear_rules.py, test/test_skills.py, test/test_proposal.py |
| Tools | scripts/shadow_compare.py, scripts/skill_client.py |
Build#
- Build the run-time library:
Runtime/build.sh. -
Open a shell of the fenced ROS 2 environment:
-
Build the package:
The package needs the message packages ds_dbw_msgs and oxts_msgs. The workspace has them in ROS/vendor. The page Build the ROS 2 Workspace has the full workspace.
Topics#
The node reads these topics with best-effort quality of service:
| Topic | Type | Use |
|---|---|---|
/oxts/ncom |
oxts_msgs/Ncom |
The packets of the pose selector |
/vehicle/odom |
nav_msgs/Odometry |
The pose for the pose sources odom and auto |
/lidar/points |
sensor_msgs/PointCloud2 |
The scan of the parameter real_scan |
/oxts/fix |
sensor_msgs/NavSatFix |
The RTK quality for the pose source odom |
/vehicle/steering/report, /vehicle/gear/report, /vehicle/wheel_speeds, /vehicle/vehicle_velocity |
ds_dbw_msgs/* |
The steering-wheel angle, the gear, the wheel speeds and the speed |
/vehicle/dbw_enabled, /safety_stop |
std_msgs/Bool |
The drive-by-wire state and the finding safety_stop |
/acres_vehicle/proposal |
std_msgs/Float64MultiArray |
The model hook |
| Output | Content |
|---|---|
/acres_vehicle/status (std_msgs/String) |
One JSON text for each control step: the mode, the state, the commands, the findings, the stops and the checker state |
/acres_vehicle/verdicts (std_msgs/String) |
The verdicts of the library for a proposal |
/vehicle/steering/cmd, /vehicle/ulc/cmd, /vehicle/gear/cmd |
The commands. DRIVE only. The gear command needs gear:=node. |
records.jsonl, events.log, result.json, commands.csv |
The record of each control step, the events, the result, and each command sent |
The service /acres_vehicle/stop (std_srvs/Trigger) stops the run.
Parameters#
| Parameter | Default | Function |
|---|---|---|
mission |
home |
F56, F53,F12 or home |
drive |
false |
true arms DRIVE: the node sends commands |
pose_source |
oxts |
oxts, odom or auto |
limits |
first_test |
first_test, reverse_test or kturn_test (both need gear:=node), or simulator |
gear |
driver |
driver: no gear publisher. node: the node shifts the gear (Gear by Wire). |
real_scan |
config |
config, level_rings or height_band (Scan of a Vehicle) |
speed_cap_mps, lateral_accel_cap_mps2, area_radius_m |
0 | A cap tighter than the limits file. 0 uses the file value. |
tables |
Empty | The cost-table file. Without it only home can start. Tables of a different map are refused. |
root, map |
The repository, the default map | The repository folder, and a map name or folder (Map Data) |
out |
~/acres_vehicle/<time>_<mission>_<mode> |
The folder of the record |
bag |
Empty | A recording. The node reads it in the recorded order. SHADOW only. |
skills, first_skill, first_skill_args |
false, empty |
The node is the skill server, and the skill that it asks for at its start |
on_cancel, client_timeout_s |
hold, 1.0 |
What a cancelled goal or a lost client gives, and the heartbeat timeout |
stop_on, stall_s, off_path_m, max_run_s |
empty, -1, 3, 0 | Findings that stop the run, and the limits of the findings stall, off_path and time |
threads, propose_wall_s, exit_at_end |
1, 0.02, true |
The pool size, the wall time of a proposal check, and the stop at the end of the run |
Modes#
SHADOW is the default. The node has no publisher on a command topic.
- The node waits for a pose and for the first message of
/lidar/points. - The library plans the mission from the pose. A refused mission ends the run with the code and the sentence.
- A timer makes one control step every 0.1 s.
- A finding that stops the run is written as "would stop" in
events.log. The run continues. - The run ends when the mission is complete and the vehicle stands, or at Ctrl-C.
DRIVE needs drive:=true. The node then sends commands:
SteeringCmdin curvature mode, inside 0.2 1/m, andUlcCmdin velocity mode, not above the speed cap.- No command before
/vehicle/dbw_enabledis true. The node never enables the drive-by-wire. - The last command is sent again at 50 Hz.
- A lost pose, lost reports or a stop finding give the safe stop: ULC 0 m/s with the last curvature, then one release message.
- When the drive-by-wire goes off, the node sends one release message and then nothing.
- Ctrl-C gives the safe stop. A second Ctrl-C stops the commands. A third Ctrl-C ends the process.
Gear by Wire#
With gear:=node in DRIVE, the node publishes /vehicle/gear/cmd and the library gets allow_gear.
- A gear command is REVERSE or the forward gear, never PARK or NEUTRAL.
- The node sends a gear command only when the vehicle stands (0.1 m/s).
- The node waits for the report to show the gear before it sends a speed in the new direction.
- A reject, a fault or no report within
gear.shift_timeout_s(4 s) gives the safe stop. forward_gear(auto,driveorlow) andreverse_speed_sign(negativeorpositive) set the forward gear and the sign of a backward speed.
Model Hook#
A process sends a proposal on /acres_vehicle/proposal. The values are in this order:
- The number of chunks.
- For each chunk:
n,dt_s,station0_m,step_m,t0_s,deadline_s, thennoffsets andnspeeds.
The chunks are in the order of preference. In the next control step, the library checks each chunk. The first accepted chunk is the proposal of the chain. The node publishes the verdicts on /acres_vehicle/verdicts.
The node loads the checker plug-in libacres_runtime_lean.so from the library folder. The variable ACRES_RUNTIME_LEAN_PLUGIN names a different file. Without the plug-in, each verdict is "no checker" and the default chain drives.
Skills#
With skills:=true, a planner drives the vehicle through skills. The ROS 2 link of the harness is a client of the node (Harness: The Link).
| Name | Type | Content |
|---|---|---|
/acres/skill |
Action acres_interfaces/action/Skill |
The goal has the skill and its arguments. The result has the code, the cause and the observation. |
/acres/observation |
std_msgs/String |
The document acres-observation-1 after each control step |
/acres/events |
std_msgs/String, latched |
Each document acres-event-1 |
/acres/clock |
std_msgs/String |
The document acres-clock-1 |
/acres/skill/heartbeat |
std_msgs/Empty, from the client |
One message every 0.5 s or faster |
python3 ROS/acres_vehicle/scripts/skill_client.py scout field=F56
python3 ROS/acres_vehicle/scripts/skill_client.py return_home
The script sends one skill, prints the events and the result, and sends the heartbeat. A client with no heartbeat loses each skill after client_timeout_s.
- In SHADOW, the node plans and tracks the skill but sends nothing.
- In DRIVE, the command between two skills, in a
waitand in astop, is ULC 0 m/s with the last curvature. - A cancelled goal or a lost client gives the skill
stop(on_cancel:=hold), or the safe stop and the end of the run (release). - The node plans a skill in a separate thread. The control loop keeps its period during the plan.
Closed Loop with ACRES Core#
The launch file launch/sim_drive.launch.py starts four programs on loopback:
| Program | Package | Function |
|---|---|---|
core_sim |
acres_core_sim |
ACRES Core in real time: the Polaris, its sensors with noise, the ray-cast LiDAR and the drive-by-wire |
sim_bridge |
acres_sim |
The ROS 2 topics of the Polaris from core_sim, and the commands to it |
lab_stubs |
acres_sim |
The stand-in of the safety driver: it enables the drive-by-wire and puts the gear lever in L |
vehicle_node |
acres_vehicle |
The node, with the pose source odom and the limits simulator |
ros2 launch acres_vehicle sim_drive.launch.py tables:=<cost tables>/dry.npz mission:=F56 drive:=true
- The pose source is
odom:/vehicle/odomwith the quality of/oxts/fix. The simulator has no/oxts/ncompackets. - The scan is the ray-cast LiDAR cloud through the switch
real_scan. - The run is in real time only. The node reads the steady clock for its steps and for the age of each message.
spawn:=enu:<east>:<north>:<yaw in degrees>starts the vehicle at a pose. The missionhomeneeds a lane within 25 m that runs along the heading.core_simhas no contact topic and no objects. Use a skill world for objects on the path.
To compare two records of the node, run:
Limits#
- The node has no contact input. It finds a contact only as the stop finding
stall. - The closed loop uses the pose source
odom. The pose sourcesoxtsandautoneed NCOM packets. - The node has no keyboard input. Stop it with Ctrl-C or the service
/acres_vehicle/stop. - The crop mask of the Scout phase is not in the node.