A212 API reference#
This page provides an auto-generated summary of Acconeer Exploration Tool’s A212 API.
Configurations#
Session#
- class acconeer.exptool.a2.SessionConfig(sensor_configs: list[SensorConfig], update_rate: float | None)#
- sensor_configs: list[SensorConfig]#
The list of sensor configs
- update_rate: float | None#
The update rate of the server.
A measurement of every sensor config in
sensor_configsis made in one update period.
- classmethod default() SessionConfig#
Creates a default SessionConfig
Example:
>>> SessionConfig.default() SessionConfig(sensor_configs=[SensorConfig(...)], update_rate=None)
- property sensor_config: SensorConfig#
Return the sole sensor config.
- Raises:
AttributeError – if len(sensor_configs) > 1
- validate() None#
Performs self-validation and validation of its sensor configs
- Raises:
ValidationError – If anything is invalid.
Sensor#
- class acconeer.exptool.a2.SensorConfig(subsweeps: list[SubsweepConfig], sweeps_per_frame: int, sweep_rate, frame_rate, inter_frame_idle_state, inter_sweep_idle_state, jitter_compensation=True)#
- subsweeps: list[SubsweepConfig]#
The list of subsweep configs
- sweeps_per_frame: int#
Sets the number of sweeps that will be captured in each frame(measurement). Can be set to 0 if e.g. only temperature measurement is wanted.
- sweep_rate: float | None#
The rate for sweeps in a frame (measurement) in Hz.
Must be > 0 or
None, whereNoneis interpreted as max sweep rate.
- frame_rate: float | None#
The frame rate in Hz.
Must be > 0 or
None, whereNoneis interpreted as max frame rate.
- inter_frame_idle_state: IdleState#
The inter frame idle state is the state the sensor idles in between each frame.
- inter_sweep_idle_state: IdleState#
The inter sweep idle state is the state the sensor idles in between each sweep in a frame.
- jitter_compensation: bool#
Enable jitter compensation
- property start_point: int#
The starting point of the sweep. The corresponding start in millimeter is approximately start_point * 2.5 mm.
- property num_points: int#
The number of data points to measure in a sweep.
- property step_length: int#
The number of steps to have between each data point.
- property profile: Profile#
Profile to use
Each profile consists of a number of settings for the sensor that configures the TX and RX paths. Lower profiles have higher depth resolution while higher profiles have higher SNR.
- property tx_antenna_mask: int#
The active TX antenna mask
- property rx_antenna_mask: int#
The active RX antenna mask
- classmethod default() SensorConfig#
Creates a default SensorConfig
- classmethod single_subsweep(*, sweeps_per_frame: int = 1, sweep_rate: float | None = None, frame_rate: float | None = None, inter_frame_idle_state: IdleState = IdleState.ARMED, inter_sweep_idle_state: IdleState = IdleState.ARMED, jitter_compensation: bool = True, **subsweep_parameters: Any) SensorConfig#
Creates a SensorConfig with a single
SubsweepConfig,The
subsweep_parametersare sent directly toSubsweepConfig’s constructor.Examples:
>>> SensorConfig.single_subsweep() SensorConfig(subsweeps=[SubsweepConfig(start_point=100, num_points=40, step_length=16, ...)], sweeps_per_frame=1, ...) >>> SensorConfig.single_subsweep(sweeps_per_frame=3, start_point=20) SensorConfig(subsweeps=[SubsweepConfig(start_point=20,...)], sweeps_per_frame=3, ...)
- classmethod identical_subsweeps(*, num_subsweeps: int, sweeps_per_frame: int = 1, sweep_rate: float | None = None, frame_rate: float | None = None, inter_frame_idle_state: IdleState = IdleState.ARMED, inter_sweep_idle_state: IdleState = IdleState.ARMED, jitter_compensation: bool = True, **subsweep_parameters: Any) SensorConfig#
Creates a
SensorConfigwithnum_subsweepsidentical subsweeps.Examples:
>>> SensorConfig.identical_subsweeps(num_subsweeps=2, num_points=37) SensorConfig(subsweeps=[SubsweepConfig(..., num_points=37, ...), SubsweepConfig(..., num_points=37, ...)], sweeps_per_frame=1, ...)
- property subsweep: SubsweepConfig#
Get the sole subsweep config.
- Raises:
AttributeError – if there is more than 1 subsweep.
>>> config = SensorConfig.identical_subsweeps(num_subsweeps=2) >>> config.subsweep Traceback (most recent call last): ... AttributeError: SensorConfig has too many subsweeps ...
- property num_subsweeps: int#
Get the number of subsweeps
- property frame_shape: tuple[int, int]#
The shape of the data array produced when measuring with this config
- validate() None#
Performs self-validation and validation of its subsweep configs
- Raises:
ValidationError – If anything is invalid.
Subsweep#
- class acconeer.exptool.a2.SubsweepConfig(*, start_point=100, num_points=40, step_length=16, profile=Profile.PROFILE_3, prf=PRF.PRF_20_8_MHZ, tx_antenna_mask=7, rx_antenna_mask=15, hwaas_max=50, hwaas_min=1, hwaas_exponent=0, receiver_gain=10, enable_tx=True)#
- start_point: int#
The starting point of the sweep. The corresponding start in millimeter is approximately start_point * 2.5 mm.
- num_points: int#
The number of data points to measure in a sweep.
- step_length: int#
The number of steps to have between each data point.
- profile: Profile#
Profile to use
Each profile consists of a number of settings for the sensor that configures the TX and RX paths. Lower profiles have higher depth resolution while higher profiles have higher SNR.
- tx_antenna_mask: int#
The active TX antenna mask
- rx_antenna_mask: int#
The active RX antenna mask
- hwaas_max: int#
Maximum Hardware accelerated average samples
If hwaas_exponent is set to 0, this value will be used for all points in the sweep.
- hwaas_min: int#
Minimum Hardware accelerated average samples
Limits the minimum number of HWAAS used for one point. When the number of HWAAS is scaled with the distance, this value limits the minimum number of HWAAS used for one point
- hwaas_exponent: int#
Hardware accelerated average samples exponent
The hwaas_exponent parameter controls how HWAAS is scaled with respect to distance during a sweep. The scaling is determined by the formula:
max(hwaas_min, hwaas_max * (d_n / d_end) ^ hwaas_exponent)
where d_n is the distance at point n and d_end is the distance at the last point in the sweep. HWAAS-scaling compensates for the energy loss of the propagating signal as it travels to and from the target.
- Commonly used values:
4: Use this for targets with a general shape. This accounts for the highest degree of energy dilution. 2: Use this for large planar targets, such as flat surfaces, where energy spreads less. 0: Use this to maintain constant HWAAS throughout the sweep. No scaling is applied, and HWAAS remains unchanged.
- receiver_gain: int#
Receiver gain
- enable_tx: bool#
Enable tx
- property num_channels: int#
The number of channels based tx_antenna_mask and rx_antenna_mask
- property end_point: int#
The end point measured by this subsweep config
- property hwaas_points: NDArray[int64]#
The hwaas values used for each point.
- validate() None#
Performs self-validation
- Raises:
ValidationError – If anything is invalid.
Parameter enums#
- class acconeer.exptool.a2.Profile#
- PROFILE_1 = 1#
- PROFILE_2 = 2#
- PROFILE_3 = 3#
- PROFILE_4 = 4#
- PROFILE_5 = 5#
- PROFILE_6 = 6#
- PROFILE_7 = 7#
- class acconeer.exptool.a2.PRF(*values)#
Pulse Repetition Frequency
Pulse Repetition Frequency, PRF, is the frequency at which pulses are sent out from the radar system. The measurement time is approximately proportional to the PRF. The higher the PRF, the shorter the measurement time.
This parameter sets the Maximum Measurable Distance, MMD, that can be achieved. MMD is the maximum value for the end point, i.e.,the start point + (number of points * step length). For example, an MMD of 7.0 m means that the range cannot be set further out than 7.0 m.
It also sets the Maximum Unambiguous Range, MUR, that can be achieved. MUR is the maximum distance at which an object can be located to guarantee that its reflection corresponds to the most recent transmitted pulse. Objects farther away than the MUR may fold into the measured range. For example, with a MUR of 11.5 m, an object at 13.5 m could become visible at 2 m.
PRF Setting
PRF
MMD
MUR
PRF_5_3_MHZ
5.3 MHz
25.0 m
28.0 m
PRF_8_3_MHZ
8.3 MHz
15.0 m
18.0 m
PRF_12_5_MHZ
12.5 MHz
9.0 m
12.0 m
PRF_15_8_MHZ
15.8 MHz
6.6 m
9.6 m
PRF_20_8_MHZ
20.8 MHz
4.2 m
7.2 m
PRF_27_7_MHZ
27.7 MHz
2.4 m
5.4 m
- PRF_5_3_MHZ = 1#
- PRF_8_3_MHZ = 2#
- PRF_12_5_MHZ = 3#
- PRF_15_8_MHZ = 4#
- PRF_20_8_MHZ = 5#
- PRF_27_7_MHZ = 6#
- property frequency: int#
Pulse repetition frequency in Hz
Entities#
RSS representations#
- class acconeer.exptool.a2.Result(...)#
Result
Represents the RSS
processing_result.- frame: NDArray[complex128]#
Frame data in a complex float data format
- tick: int#
Server tick when the server got the interrupt from the sensor
- data_saturated: list[bool]#
Indication of sensor data being saturated, can cause data corruption. Lower the receiver gain if this indication is set.
- measured_sweep_rate: float | None#
Sweep rate measured by RSS. This value might differ from the configured sweep rate since the configured sweep rate represents the maximum requested sweep rate, whereas the measured sweep rate reflects the actual rate achieved during operation, which may be lower if the sensor cannot keep up with the requested speed.
If the configuration includes only a single sweep per frame, the measured sweep rate will be
None.
- frame_delayed: bool#
Indication of a delayed frame.
A frame is considered delayed when it could not be measured at the specified frame rate. This means that only a set frame rate can produce delayed frames. If the frame rate is uncapped, the frame cannot be delayed.
The frame rate might need to be lowered if this indication is set.
- calibration_temperature: int#
The temperature of previously performed calibration
- calibration_needed: bool#
Whether the current calibration has become invalid.
Recalibration is performed by setting up a new session (see
acconeer.exptool.a2.Client.setup_session()).
- seconds_since_server_start(ticks_per_second: int) float#
Return how many seconds the server has been running before producing this result
- seconds_since_tick(ticks_per_second: int, tick: int) float#
Return how many seconds has elapsed between the specified server tick and this result.
Note that the specified tick needs to be less than this Result’s tick.
- property int16_complex_frame: NDArray[Any]#
Frame data in the original data format (complex int16)
- get_subframe(config: SensorConfig, subsweep_index: int, channel_indexes: Container[int] = ALL) NDArray[complex128]#
Get the list of subframes (data collected by a subsweep) given a SensorConfig
The channel index is Tx-major
Examples:
>>> r = Result(frame=np.array([[0.+0.j, 1.+1.j, 2.+2.j, 3.+3.j], ... [4.+4.j, 5.+5.j, 6.+6.j, 7.+7.j]]), ... temperature=21, tick=0, data_saturated=[False], ... measured_sweep_rate=7.35, frame_delayed=False, ... calibration_temperature=25, calibration_needed=False) ... >>> config = SensorConfig.single_subsweep(num_points=4, tx_antenna_mask=0b001, rx_antenna_mask=0b0001) >>> r.get_subframe(config, 0) array([[0.+0.j, 1.+1.j, 2.+2.j, 3.+3.j], [4.+4.j, 5.+5.j, 6.+6.j, 7.+7.j]])
>>> config = SensorConfig.identical_subsweeps(num_subsweeps=2, num_points=2, tx_antenna_mask=0b001, rx_antenna_mask=0b0001) >>> r.get_subframe(config, 0) array([[0.+0.j, 1.+1.j], [4.+4.j, 5.+5.j]]) >>> r.get_subframe(config, 1) array([[2.+2.j, 3.+3.j], [6.+6.j, 7.+7.j]])
It’s also possible to extract only the data of specified channels using
channel_indexes:>>> config_2_channels = SensorConfig.identical_subsweeps(num_subsweeps=2, ... num_points=1, ... tx_antenna_mask=0b001, ... rx_antenna_mask=0b0011) ... >>> r.get_subframe(config_2_channels, 0, channel_indexes=[1]) array([[1.+1.j], [5.+5.j]]) >>> r.get_subframe(config_2_channels, 1, channel_indexes=[1]) array([[3.+3.j], [7.+7.j]])
Other#
- class acconeer.exptool.a2.Metadata(tick_period: int, sensor_calibration: str | None, update_period: float | None)#
- tick_period: int#
- sensor_calibration: str | None#
- update_period: float | None#
- class acconeer.exptool.a2.GroupResult(results: list[Result])#
Group result
Represent the result of an Exploration Server group (multiple results)
- property frame: NDArray#
Frame data in a complex float data format
- property tick: int#
Server tick when the server got the interrupt from the sensor
- property data_saturated: list#
Indication of sensor data being saturated, can cause data corruption. Lower the receiver gain if this indication is set.
- property measured_sweep_rate: float#
Sweep rate measured by RSS. This value might differ from the configured sweep rate since the configured sweep rate represents the maximum requested sweep rate, whereas the measured sweep rate reflects the actual rate achieved during operation, which may be lower if the sensor cannot keep up with the requested speed.
If the configuration includes only a single sweep per frame, the measured sweep rate will be
None.
- class acconeer.exptool.a2.AntennaArray(*values)#
Antenna arrays of the A2 sensor packages, with antenna positions and channel corrections
- AP212 ...#
- get_correction_scalar(channel_number: int, az: float, el: float = 0.0, *, profile: Profile) complex#
Get a correction scalar for the given channel, angles (in radians) and profile
Uses chebval2d if the profile’s table is 3D (az, el correction); falls back to chebval (az-only) for a 2D table.
- get_nominal_steering_scalar(channel_number: int, az: float, el: float) complex#
Get a steering scalar for the given channel and angles (in radians)
The channel number is Tx-major.
- get_steering_vector(az: float, el: float, rx_mask: int, tx_mask: int, corrected: bool = True, *, profile: Profile) NDArray[complex128]#
Get the steering vector for all channels, given angles (in radians) and profile
The returned steering vector is indexed by channel index (Tx-major)
See :py:meth:
AntennaArray.get_steering_scalar.
- get_steering_vectors(az_angles: NDArray[float64], el_angles: NDArray[float64], tx_antenna_mask: int, rx_antenna_mask: int, *, profile: Profile) NDArray[complex128]#
Calculate steering vectors for all az/el angle combinations, for the given profile.
Returns an array of shape (num_az, num_el, num_channels).
- channels(tx_mask: int, rx_mask: int) dict[int, Channel]#
Get the channels in this antenna array.
The keys in the returned dict are the Tx-major channel numbers. If the AntennaArray does not contain all antennas masked in by the passed masks, those will silently be omitted.
>>> AntennaArray.AP212.channels(rx_mask=0b1111, tx_mask=0b111) {0: Channel(tx=Pos(x=-7.5, y=0.0, z=2.5), rx=Pos(x=-2.5, y=0.0, z=2.5)), 1: Channel(tx=Pos(x=-7.5, y=0.0, z=2.5), rx=Pos(x=-2.5, y=0.0, z=0.0)), 2: Channel(tx=Pos(x=-7.5, y=0.0, z=2.5), rx=Pos(x=0.0, y=0.0, z=0.0)), 3: Channel(tx=Pos(x=-7.5, y=0.0, z=2.5), rx=Pos(x=2.5, y=0.0, z=0.0)), 4: Channel(tx=Pos(x=7.5, y=0.0, z=2.5), rx=Pos(x=-2.5, y=0.0, z=2.5)), 5: Channel(tx=Pos(x=7.5, y=0.0, z=2.5), rx=Pos(x=-2.5, y=0.0, z=0.0)), 6: Channel(tx=Pos(x=7.5, y=0.0, z=2.5), rx=Pos(x=0.0, y=0.0, z=0.0)), 7: Channel(tx=Pos(x=7.5, y=0.0, z=2.5), rx=Pos(x=2.5, y=0.0, z=0.0)), 8: Channel(tx=Pos(x=0.0, y=0.0, z=2.5), rx=Pos(x=-2.5, y=0.0, z=2.5)), 9: Channel(tx=Pos(x=0.0, y=0.0, z=2.5), rx=Pos(x=-2.5, y=0.0, z=0.0)), 10: Channel(tx=Pos(x=0.0, y=0.0, z=2.5), rx=Pos(x=0.0, y=0.0, z=0.0)), 11: Channel(tx=Pos(x=0.0, y=0.0, z=2.5), rx=Pos(x=2.5, y=0.0, z=0.0))}
Client#
- class acconeer.exptool.a2.Client(*args: Any, **kwargs: Any)#
- class ResultFormat(*values)#
Decide the format of the data returned by
Client.get_next- AUTO = 1#
- FULL = 3#
- SOLE = 2#
- classmethod open(ip_address: str | None = None, tcp_port: int | None = None, serial_port: str | None = None, usb_device: str | bool | None = None, mock: bool | None = None, override_baudrate: int | None = None, flow_control: bool = True, generation: str | None = 'a2') Self#
Open a new client
- abstractmethod close() None#
Closes the connection to the host
- get_next() GroupResult | Result#
- get_next(*, format: te.Literal[AUTO]) GroupResult | Result
- get_next(*, format: te.Literal[FULL]) GroupResult
- get_next(*, format: te.Literal[SOLE]) Result
Gets results from the server.
- Parameters:
format –
Decides the format of the returned result.
- AUTO
return a
Resultif the setupSessionConfighas exactly oneSensorConfig,GroupResultotherwise.
- SOLE
Always return a
Result, raises an error if the setupSessionConfighas more than oneSensorConfig.
- FULL
Always return
GroupResult
- Returns:
See
format.- Raises:
ClientErrorif the session is not started or a soleResultcould not be received.
- abstractmethod setup_session(config: SessionConfig, calibration: str | None = None) Metadata#
Sets up the session specified by
configA session is typically setup by performing radar calibration on the Exploration Server.
Sensor calibrations may be reused by reading it from
Metadata.sensor_calibrationpassing it to thecalibrationparameter.
- abstractmethod start_session() None#
Starts the already set up session.
After this call, the server starts streaming data to the client.
- Raises:
ClientErrorifClient’s session is not set up.
- stop_session() None#
Stops an on-going session
- Raises:
ClientErrorifClient’s session is not started.
- property calibration: str#
Returns the calibration string if calibration was performed in setup_session(),
- Raises:
ClientErrorifClientdid not provide calibration.
- property calibration_provided: bool#
Returns whether a calibration was provided in setup_session.
- property client_info: ClientInfo#
The
ClientInfo.
- property connected: bool#
Whether this Client is connected.
- abstract property server_info: ServerInfo#
The
ServerInfo
- property session_config: SessionConfig#
The
SessionConfigthis client is setup with
- property session_is_setup: bool#
Whether this Client has a session set up.
- property session_is_started: bool#
Whether this Client’s session is started.
- property tick_period: int#
The theoretical number of ticks between results
Recording#
Recorder#
- class acconeer.exptool.a2.H5Recorder(path_or_file: PathOrH5File, attachable: RecorderAttachable[Recorder[SessionConfig, Metadata, GroupResult, ServerInfo]] | None = None, mode: str = 'x', *, _chunk_size: int | None = None, _lib_version: str | None = None, _timestamp: str | None = None, _uuid: str | None = None)#
Recorder writing directly to an HDF5 file
- Parameters:
path_or_file –
If a path-like object, by default (depending on
modebelow) an HDF5 file is created at that path. When stopping, the file is closed.If an
h5py.File, that file is used as-is. In this case, the file is not closed when stopping.attachable – A
Clientthat the recorder will be attached to. When a recorder is attached to aClient, all metadata and data frames will be recorded.mode – The file mode to use if a path-like object was given for
path_or_file. Default value is ‘x’, meaning that we open for exclusive creation, failing if the file already exists._chunk_size –
If given, data will be written to file every
_chunk_sizesamples.If not given, data will be written at least every 512:th sample, or at least once per second, whichever comes first.
Setting a small chunk size (e.g. 1) may degrade performance for high sample rates.
Internal parameter, subject to change.
Record#
- class acconeer.exptool.a2.H5Record(file: h5py.File, chunk_size: int = 100, schema: te.ClassVar[type[SessionSchema]] = <class 'acconeer.exptool._core.recording.h5_session_schema.SessionSchema'>)#
- file: File#
- property client_info: ClientInfo#
- property lib_version: str#
- property server_info: ServerInfo#
- property timestamp: str#
- property uuid: str#
- close() None#
- require_algo_group(key: str) Group#
- session(session_index: int) H5SessionRecord#
- property num_sessions: int#
- property group_results: Iterator[GroupResult]#
- property num_frames: int#
- property session_config: SessionConfig#
Open Record#
- acconeer.exptool.a2.open_record(path_or_file: PathOrH5File) H5Record#
Open a record from file
Since this function returns a
H5Record, data is not immediately loaded into memory. Rather, data is lazily loaded from the underlying file on demand.Either a path or an opened file (
h5py.File) may be given. If a path is given, the file will be opened by this function, and must be closed again by the user. The recommended way to do this is by using the context manager of the returned persistent record, like:with a2.open_record("path/to/my/file.h5") as record: record.timestamp
- Returns:
A
H5Recordwrapping the given file