AP_Scripting: Add drivers for NoopLoop TOFSense-M CAN and Serial sensors

This commit is contained in:
rishabsingh3003 2023-07-05 01:12:34 +05:30 committed by Randy Mackay
parent b6a54bbef9
commit 153ff58bd9
4 changed files with 630 additions and 0 deletions

View File

@ -0,0 +1,291 @@
--[[
Driver for NoopLoop TOFSense-M CAN Version. Can be used as a 1-D RangeFidner or 3-D proximity sensor. Upto 3 CAN devices supported in this script although its easy to extend.
--]]
local update_rate_ms = 10 -- update rate (in ms) of the driver. 10ms was found to be appropriate
-- Global variables (DO NOT CHANGE)
local param_num_lua_driver_backend = 36 -- parameter number for lua rangefinder
local param_num_lua_prx_backend = 15 -- parameter number for lua proximity
local sensor_setup_done = false
-- Table contains the following info for 3 sensors. If more sensors are needed, this table will need to be increased
-- approportate scritping backend from rngfnd/prx library, true if backend exists, index parsed last from sensor, minimum distance found since index was 0, Param to decide which rngfnd/prx backednd will match to this sensor, param to decide CAN ID of this sensor
local backend_driver = {
{lua_driver_backend = nil, sensor_driver_found = false, last_index = 0, min_distance = 0, INSTANCE, CAN_ID},
{lua_driver_backend = nil, sensor_driver_found = false, last_index = 0, min_distance = 0, INSTANCE, CAN_ID},
{lua_driver_backend = nil, sensor_driver_found = false, last_index = 0, min_distance = 0, INSTANCE, CAN_ID}
}
local PARAM_TABLE_KEY = 104
local PARAM_TABLE_PREFIX = "TOFSENSE_"
-- bind a parameter to a variable
function bind_param(name)
local p = Parameter()
assert(p:init(name), string.format('could not find %s parameter', name))
return p
end
-- add a parameter and bind it to a variable
function bind_add_param(name, idx, default_value)
assert(param:add_param(PARAM_TABLE_KEY, idx, name, default_value), string.format('could not add param %s', name))
return bind_param(PARAM_TABLE_PREFIX .. name)
end
-- setup parameters
assert(param:add_table(PARAM_TABLE_KEY, PARAM_TABLE_PREFIX, 15), 'could not add param table')
--[[
// @Param: TOFSENSE_PRX
// @DisplayName: TOFSENSE-M to be used as Proximity sensor
// @Description: Set 0 if sensor is to be used as a 1-D rangefinder (minimum of all distances will be sent, typically used for height detection). Set 1 if it should be used as a 3-D proximity device (Eg. Obstacle Avoidance)
// @Values: 0:Set as Rangefinder, 1:Set as Proximity sensor
// @User: Standard
--]]
SET_PRX = bind_add_param('PRX', 1, 0)
--[[
// @Param: TOFSENSE_NO
// @DisplayName: TOFSENSE-M Connected
// @Description: Number of TOFSENSE-M CAN sensors connected
// @Range: 1 3
// @User: Standard
--]]
MAX_SENSORS = bind_add_param('NO', 2, 1)
--[[
// @Param: TOFSENSE_MODE
// @DisplayName: TOFSENSE-M mode to be used
// @Description: TOFSENSE-M mode to be used. 0 for 8x8 mode. 1 for 4x4 mode
// @Values: 0: 8x8 mode, 1: 4x4 mode
// @User: Standard
--]]
MODE = bind_add_param('MODE', 3, 0)
-- first sensor
--[[
// @Param: TOFSENSE_INST1
// @DisplayName: TOFSENSE-M First Instance
// @Description: First TOFSENSE-M sensors backend Instance. Setting this to 1 will pick the first backend from PRX_ or RNG_ Parameters (Depending on TOFSENSE_PRX)
// @Range: 1 3
// @User: Standard
--]]
backend_driver[1].INSTANCE = bind_add_param('INST1', 4, 1)
--[[
// @Param: TOFSENSE_ID1
// @DisplayName: TOFSENSE-M First ID
// @Description: First TOFSENSE-M sensor ID. Leave this at 0 to accept all IDs and if only one sensor is present. You can change ID of sensor from NAssistant Software
// @Range: 1 255
// @User: Standard
--]]
backend_driver[1].CAN_ID = bind_add_param('ID1', 5, 0)
-- second sensor
--[[
// @Param: TOFSENSE_INST2
// @DisplayName: TOFSENSE-M Second Instance
// @Description: Second TOFSENSE-M sensors backend Instance. Setting this to 2 will pick the second backend from PRX_ or RNG_ Parameters (Depending on TOFSENSE_PRX)
// @Range: 1 3
// @User: Standard
--]]
backend_driver[2].INSTANCE = bind_add_param('INST2', 6, 2)
--[[
// @Param: TOFSENSE_ID2
// @DisplayName: TOFSENSE-M Second ID
// @Description: Second TOFSENSE-M sensor ID. This cannot be 0. You can change ID of sensor from NAssistant Software
// @Range: 1 255
// @User: Standard
--]]
backend_driver[2].CAN_ID = bind_add_param('ID2', 7, 2)
--third sensor
--[[
// @Param: TOFSENSE_INST3
// @DisplayName: TOFSENSE-M Third Instance
// @Description: Third TOFSENSE-M sensors backend Instance. Setting this to 3 will pick the second backend from PRX_ or RNG_ Parameters (Depending on TOFSENSE_PRX)
// @Range: 1 3
// @User: Standard
--]]
backend_driver[2].INSTANCE = bind_add_param('INST3', 8, 2)
--[[
// @Param: TOFSENSE_ID3
// @DisplayName: TOFSENSE-M Thir ID
// @Description: Third TOFSENSE-M sensor ID. This cannot be 0. You can change ID of sensor from NAssistant Software
// @Range: 1 255
// @User: Standard
--]]
backend_driver[2].CAN_ID = bind_add_param('ID3', 9, 3)
-- check both CAN device for scripting backend. CAN Buffer length set to fixed 5
local driver = CAN:get_device(5)
if not driver then
driver = CAN:get_device2(5)
end
if not driver then
error("No scripting CAN interfaces found")
return
end
function setup_sensor(sensor, param_num)
local sensor_count = sensor:num_sensors() -- number of sensors connected
if MAX_SENSORS:get() > 3 then
error("TOFSENSE: Only 3 devices supported")
end
for i = 1, MAX_SENSORS:get() do
local backends_found = 0
local sensor_driver_found = false
local lua_driver_backend
for j = 0, sensor_count -1 do
local device = sensor:get_backend(j)
if ((not sensor_driver_found) and device and (device:type() == param_num)) then
-- this is a lua driver
backends_found = backends_found + 1
if backends_found == backend_driver[i].INSTANCE:get() then
-- get the correct instance as we may have multile scripting backends doing different things
sensor_driver_found = true
lua_driver_backend = device
end
end
end
if not sensor_driver_found then
-- We can't use this script if user hasn't setup a lua backend
error(string.format("TOFSENSE: Could not find SCR Backend ".. tostring(i)))
return
end
backend_driver[i].sensor_driver_found = true
backend_driver[i].lua_driver_backend = lua_driver_backend
end
end
-- get yaw and pitch of the pixel based message index.
function convert_to_angle(index)
-- The distances are sent in either a 4x4 or 8x8 grid. The horizontal and vertical FOV are 45 degrees so we can work out the angles
local index_row_max = 8
if (MODE:get() ~= 0) then
index_row_max = 4
end
local angle_division = 45/index_row_max
local horizontal_index = (index) % index_row_max
local vertical_index = math.floor(index / index_row_max)
local yaw = -22.5 + (horizontal_index*angle_division)
local pitch = -22.5 + (vertical_index*angle_division)
return yaw, pitch
end
-- send the message down to proximity library. This needs to be a 3D vector
function sent_prx_message(prx_backend, dist, yaw_deg, pitch_deg, push_to_boundary)
if (dist > 0) then
prx_backend:set_distance_min_max(0,4)
prx_backend:handle_script_distance_msg(dist, yaw_deg, pitch_deg, push_to_boundary)
end
end
-- send the message down to proximity library. This needs to be a single distance
function send_rfnd_message(rfnd_backend, dist)
if dist > 0 and (SET_PRX:get() == 0) then
local sent_successfully = rfnd_backend:handle_script_msg(dist)
if not sent_successfully then
-- This should never happen as we already checked for a valid configured lua backend above
gcs:send_text(0, string.format("RFND Lua Script Error"))
end
end
end
-- get the correct instance from parameters according to the CAN ID received
function get_instance_from_CAN_ID(frame)
for i = 1, MAX_SENSORS:get() do
if ((uint32_t(frame:id() - 0x200)) == uint32_t(backend_driver[i].CAN_ID:get())) then
return i
end
end
return 0
end
-- this is the loop which periodically runs
function update()
-- setup the sensor according to user preference of using proximity library or rangefinder
if not sensor_setup_done then
if SET_PRX:get() == 0 then
setup_sensor(rangefinder, param_num_lua_driver_backend)
else
setup_sensor(proximity, param_num_lua_prx_backend)
end
sensor_setup_done = true
end
-- read frame if available
local frame = driver:read_frame()
if not frame then
return
end
local instance
if ((backend_driver[1].CAN_ID:get() ~= 0)) then
instance = get_instance_from_CAN_ID(frame)
if (instance == 0) then
-- wrong ID
return
end
else
-- Simply accept any ID
instance = 1
end
-- Correct ID, so parse the data
local distance = ((frame:data(0)<<8 | frame:data(1)<<16 | frame:data(2)<<24)/256) / 1000
local status = frame:data(3)
local index = frame:data(6)
local update_rfnd = false
if (index < backend_driver[instance].last_index) then
-- One cycle of data has come. Lets update all backends involved
if SET_PRX:get() == 1 then
backend_driver[instance].lua_driver_backend:update_virtual_boundary()
else
update_rfnd = true
end
end
backend_driver[instance].last_index = index
if status < 255 then
-- Status is healthy
if (SET_PRX:get() == 1) then
-- Send 3D data to Proximity Library
local yaw, pitch = convert_to_angle(index)
sent_prx_message(backend_driver[instance].lua_driver_backend, distance, yaw, pitch, false)
end
if (backend_driver[instance].min_distance == 0 or distance < backend_driver[instance].min_distance) then
-- store min data incase user wants to use it as a 1-D RangeFinder
backend_driver[instance].min_distance = distance
end
end
if (update_rfnd) then
send_rfnd_message(backend_driver[instance].lua_driver_backend, backend_driver[instance].min_distance)
-- reset
backend_driver[instance].min_distance = 0
end
end
-- wrapper around update(). This calls update() and if update faults
-- then an error is displayed, but the script is not stopped
function protected_wrapper()
local success, err = pcall(update)
if not success then
gcs:send_text(MAV_SEVERITY_ERROR, "Internal Error: " .. err)
-- when we fault we run the update function again after 1s, slowing it
-- down a bit so we don't flood the console with errors
return protected_wrapper, 1000
end
return protected_wrapper, update_rate_ms
end
-- start running update loop
return protected_wrapper()

View File

@ -0,0 +1,50 @@
# TOFSense-M CAN Driver
TOFSense-M CAN Driver lua script. Only Copter/Rover/Plane 4.5 and above
## How to use - Pre-Configuration
- Connect sensors to autopilot's CAN1 port or CAN2 port
- If connected to CAN1, set CAN_D1_PROTOCOL = 10 (Scripting), CAN_P1_DRIVER = 1 (First driver)
- If connected to CAN2, set CAN_D2_PROTOCOL = 10 (Scripting), CAN_P2_DRIVER = 2 (Second driver)
- Set SCR_ENABLE = 1 to enable scripting
- Set SCR_HEAP_SIZE = 150000 (or higher)
- If using the sensor as a 1-D Rangefinder (typically for terrain following); set RNGFND1_TYPE = 36 (Scripting) to enable the rangefinder scripting driver
- If using the sensor as a 3-D Proximity sensor (typically for obstacle); set PRX1_TYPE = 15 (Scripting) to enable the proximity scripting driver
- Reboot the autopilot
- Copy the TOFSense-M_CAN.lua script to the autopilot's SD card in the APM/scripts directory and reboot the autopilot
## How to use - Script Parameter Configuration
If everything above is done correctly, new "TOFSENSE_" parameters should be visible (only after script loads. Please refresh parameters if not visible). Script parameters to adjust are listed below
### TOFSENSE_PRX
If you have set RNGFND1_TYPE = 36, then set this as 0
If you have set PRX1_TYPE = 15, then set this as 1
Any change in this parameter will require a reboot (or scripting restart), ignore any errors on change before reboot. Make sure RNGFND/PRX is configured before setting this.
### TOFSENSE_NO
Total number of TOFSense-M CAN sensors connected on the bus. Change will require a reboot
### TOFSENSE_MODE
TOFSENSE-M mode to be used.
- 0 for 8x8 mode.
- 1 for 4x4 mode.
All sensors must be in same mode. You can change the mode of sensor from NAssistant Software
### TOFSENSE_ID1
First TOFSENSE-M sensor ID. Leave this at 0 to accept all IDs and if only one sensor is present. You can change ID of sensor from NAssistant Software.
### TOFSENSE_INST1
First TOFSENSE-M sensors RNGFND_/PRX_ Instance
Setting this to 1 will pick the first backend from PRX_ or RNG_ Parameters.
So for example if RNGFND1_TYPE = 36, RNGFND2_TYPE = 36, then you can set this parameter to 2, to pick RNGFND2_ parameters to configure this sensor
### Configuring more than one sensor on same CAN bus
As described above, TOFSENSE_INST2, TOFSENSE_ID2 and TOFSENSE_INST3, TOFSENSE_ID3 can be adjusted so to support multiple sensors

View File

@ -0,0 +1,252 @@
--[[
Upto 3 CAN devices supported in this script although its easy to extend.
--]]
local sensor_no = 1 -- Sensor ID. Upload a copy of this script to the flight controller with this variable changed if you would like to use multiple of these sensors as serial. Switching to CAN highly recommended in that case
local update_rate_ms = 10 -- update rate (in ms) of the driver. 10ms was found to be appropriate
local bytes_to_parse = 100 -- serial bytes to parse in one interation of lua script. Reduce this if script is not able to complete in time
local debug_enable = false -- helpgul debug GCS prints
-- Global variables (DO NOT CHANGE)
local NOOPLOOP_FRAME_HEADER = 0x57
local NOOPLOOP_FRAME_HEADER_1 = 0x01
local param_num_lua_driver_backend = 36 -- parameter number for lua rangefinder
local param_num_lua_prx_backend = 15 -- parameter number for lua proximity
local lua_driver_backend -- store lua backend here
local sensor_driver_found = false -- true if user has configured lua backend
local num_pixels = 16 -- automatically updated if 64. User can select between 16/64 from NAssistant software
local total_bytes_to_expect = 112 -- total bytes in one complete packet
local linebuf = {} -- serial buffer
local linebuf_len = 0
local index_row_max = 8
local PARAM_TABLE_KEY = 109 + sensor_no
local PARAM_TABLE_PREFIX = string.format("TOFSENSE_S" .. sensor_no.. "_")
-- bind a parameter to a variable
function bind_param(name)
local p = Parameter()
assert(p:init(name), string.format('could not find %s parameter', name))
return p
end
-- add a parameter and bind it to a variable
function bind_add_param(name, idx, default_value)
assert(param:add_param(PARAM_TABLE_KEY, idx, name, default_value), string.format('could not add param %s', name))
return bind_param(PARAM_TABLE_PREFIX .. name)
end
-- setup parameters
assert(param:add_table(PARAM_TABLE_KEY, PARAM_TABLE_PREFIX, 3), 'could not add param table')
--[[
// @Param: TOFSENSE_S1_PRX
// @DisplayName: TOFSENSE-M to be used as Proximity sensor
// @Description: Set 0 if sensor is to be used as a 1-D rangefinder (minimum of all distances will be sent, typically used for height detection). Set 1 if it should be used as a 3-D proximity device (Eg. Obstacle Avoidance)
// @Values: 0:Set as Rangefinder, 1:Set as Proximity sensor
// @User: Standard
--]]
SET_PRX = bind_add_param('PRX', 1, 0)
--[[
// @Param: TOFSENSE_S1_SP
// @DisplayName: TOFSENSE-M serial port config
// @Description: UART instance sensor is connected to. Set 1 if sensor is connected to the port with fist SERIALx_PROTOCOL = 28.
// @Range: 1 4
// @User: Standard
--]]
SERIAL_PORT = bind_add_param('SP', 2, 1)
--[[
// @Param: TOFSENSE_S1_BR
// @DisplayName: TOFSENSE-M serial port baudrate
// @Description: Serial Port baud rate. Sensor baud rate can be changed from Nassistant software
// @User: Standard
--]]
SERIAL_BAUD = bind_add_param('BR', 3, 230400)
-- find the serial scripting serial port instance. 0 indexed.
-- SERIALx_PROTOCOL 28
local port = assert(serial:find_serial(SERIAL_PORT:get() - 1),"Could not find Scripting Serial Port")
-- begin the serial port
port:begin(SERIAL_BAUD:get())
-- port:set_flow_control(0)
function setup_sensor(sensor, param_num)
local sensor_count = sensor:num_sensors() -- number of sensors connected
for j = 0, sensor_count -1 do
local device = sensor:get_backend(j)
if ((not sensor_driver_found) and device and (device:type() == param_num)) then
-- this is a lua driver
sensor_driver_found = true
lua_driver_backend = device
end
end
if not sensor_driver_found then
-- We can't use this script if user hasn't setup a lua backend
gcs:send_text(0, string.format("Configure Lua Sensor"))
return
end
end
-- get yaw and pitch of the pixel based message index.
function convert_to_angle(index)
-- The distances are sent in either a 4x4 or 8x8 grid. The horizontal and vertical FOV are 45 degrees so we can work out the angles
local angle_division = 45/index_row_max
local horizontal_index = (index) % index_row_max
local vertical_index = math.floor(index / index_row_max)
local yaw = -22.5 + (horizontal_index*angle_division)
local pitch = -22.5 + (vertical_index*angle_division)
return yaw, pitch
end
-- send the message down to proximity library. This needs to be a 3D vector. User of this function needs to ensure prx backend exists
function sent_prx_message(dist, yaw_deg, pitch_deg, push_to_boundary)
if dist > 0 then
lua_driver_backend:set_distance_min_max(0,4)
lua_driver_backend:handle_script_distance_msg(dist, yaw_deg, pitch_deg, push_to_boundary)
end
end
-- send the message down to proximity library. This needs to be a single distance. User of this function needs to ensure rngfnd backend exists
function send_rfnd_message(dist)
if dist > 0 then
local sent_successfully = lua_driver_backend:handle_script_msg(dist)
if not sent_successfully then
-- This should never happen as we already checked for a valid configured lua backend above
gcs:send_text(0, string.format("RFND Lua Script Error"))
end
end
end
function update() -- this is the loop which periodically runs
if not sensor_driver_found then
if SET_PRX:get() == 0 then
setup_sensor(rangefinder, param_num_lua_driver_backend)
else
setup_sensor(proximity, param_num_lua_prx_backend)
end
end
if (not sensor_driver_found) then
-- We can't use this script if user hasn't setup a lua backend
return
end
local nbytes = port:available()
nbytes = math.min(nbytes, bytes_to_parse)
while nbytes > 0 do
nbytes = nbytes - 1
local r = port:read()
if r < 0 then
break
end
local c = r
-- if buffer is empty and this byte is 0x57, add to buffer
if linebuf_len == 0 then
if c == NOOPLOOP_FRAME_HEADER then
-- lua table indexing starts from 1
linebuf[linebuf_len + 1] = c
linebuf_len = linebuf_len + 1
else
linebuf_len = 0
end
elseif linebuf_len == 1 then
-- if buffer has 1 element and this byte is 0x00, add it to buffer
-- if not clear the buffer
if c == NOOPLOOP_FRAME_HEADER_1 then
linebuf[linebuf_len + 1] = c
linebuf_len = linebuf_len + 1
else
linebuf_len = 0
end
elseif linebuf_len == 8 then
-- store the next character as "number of pixels"
num_pixels = tonumber(c)
linebuf[linebuf_len + 1] = c
linebuf_len = linebuf_len + 1
-- Check if num_pixels is either 64 or 16
if num_pixels ~= 64 and num_pixels ~= 16 then
linebuf_len = 0
end
--update total bytes to expect
total_bytes_to_expect = 16 + (num_pixels * 6)
if num_pixels == 16 then
index_row_max = 4
end
else
-- add character to buffer
linebuf[linebuf_len + 1] = c
linebuf_len = linebuf_len + 1
if linebuf_len == total_bytes_to_expect then
-- calculate checksum
local checksum = 0
for i = 1, total_bytes_to_expect - 1 do
checksum = (checksum + linebuf[i]) % 256
end
-- if checksum matches extract contents
if checksum ~= linebuf[total_bytes_to_expect] then
if debug_enable then
gcs:send_text(0, "Checksum does not matches")
end
else
local min_distance = 0
local min_index = 0
local index = -1
for i = 10, total_bytes_to_expect - 7, 6 do
local distance = ((linebuf[i]<<8 | linebuf[i+1]<<16 | linebuf[i+2]<<24)/256) / 1000000
local status = linebuf[i+3]
index = index + 1
if status < 255 then
if (SET_PRX:get() == 1) then
local yaw, pitch = convert_to_angle(index)
if debug_enable then
gcs:send_text(0, "Distance debug: " .. distance .. " mm, status: " .. status .. "Yaw " .. yaw .. "pitch " .. pitch)
end
sent_prx_message(distance, yaw, pitch, false)
end
if status == 0 and (min_distance == 0 or distance < min_distance) then
min_distance = distance
min_index = index
end
end
end
if (SET_PRX:get() == 1) then
-- update prx boundary now that we have parsed all data
lua_driver_backend:update_virtual_boundary()
else if min_distance > 0 then
if debug_enable then
local yaw,pitch = convert_to_angle(min_index)
gcs:send_text(0, "Distance: " .. min_distance .. " m. Yaw " .. yaw .. "pitch " .. pitch)
end
send_rfnd_message(min_distance)
end
end
end
-- clear buffer
linebuf_len = 0
end
end
end
end
-- wrapper around update(). This calls update() and if update faults
-- then an error is displayed, but the script is not stopped
function protected_wrapper()
local success, err = pcall(update)
if not success then
gcs:send_text(MAV_SEVERITY_ERROR, "Internal Error: " .. err)
-- when we fault we run the update function again after 1s, slowing it
-- down a bit so we don't flood the console with errors
return protected_wrapper, 1000
end
return protected_wrapper, update_rate_ms
end
-- start running update loop
return protected_wrapper()

View File

@ -0,0 +1,37 @@
# TOFSense-M Serial Driver
TOFSense-M Serial Driver lua script. Only Copter/Rover/Plane 4.5 and above
## How to use - Pre-Configuration
- Connect sensors to one of autopilot's Serial port
- Set SERIALx_PROTOCOL 28
- Set SCR_ENABLE = 1 to enable scripting
- Set SCR_HEAP_SIZE = 150000 (or higher)
- If using the sensor as a 1-D Rangefinder (typically for terrain following); set RNGFND1_TYPE = 36 (Scripting) to enable the rangefinder scripting driver
- If using the sensor as a 3-D Proximity sensor (typically for obstacle); set PRX1_TYPE = 15 (Scripting) to enable the proximity scripting driver
- Reboot the autopilot
- Copy the TOFSense-M_Serial.lua script to the autopilot's SD card in the APM/scripts directory and reboot the autopilot
## How to use - Script Parameter Configuration
If everything above is done correctly, new "TOFSENSE_S_" parameters should be visible (only after script loads. Please refresh parameters if not visible). Script parameters to adjust are listed below. Any changes would require reboot
### TOFSENSE_S1_PRX
If you have set RNGFND1_TYPE = 36, then set this as 0
If you have set PRX1_TYPE = 15, then set this as 1
Any change in this parameter will require a reboot (or scripting restart), ignore any errors on change before reboot. Make sure RNGFND/PRX is configured before setting this.
### TOFSENSE_S1_SP
UART instance sensor is connected to. Set 1 if sensor is connected to the port with fist SERIALx_PROTOCOL = 28. For example, if SERIAL1_PROTOCOL = 28, and SERIAL2_PROTOCOL = 28, then setting this parameter 2 would assume the SERIAL2 port is attached to the sensor
### TOFSENSE_S1_BR
Serial Port baud rate. Sensor baud rate of the sensor can be changed from Nassistant software
## Advanced: Configuring more than one sensor on different Serial ports
It is not recommended to use this driver for more than one sensor. However, it is possible if you wish to do it.
Simply make a copy of the lua script, open it and change the first line "local sensor_no = 1" to "local sensor_no = 2" and upload that script along side the first script.
Once a reboot is done, new TOFSENSE_S2_ parameters should be visible which can be configured as described above.