Badan pengatur pemerintah menerapkan beberapa persyaratan untuk memastikan bahwa visibilitas belakang tidak langsung memberikan informasi yang cukup untuk memanuver kendaraan secara tepat dan tepat waktu. Hal ini memengaruhi kesadaran pengemudi terhadap lingkungan sekitar.
Untuk sistem visibilitas belakang berdasarkan Sistem Pemantauan Kamera (CMS), National Highway Traffic Safety Administration (NHTSA) mewajibkan Anda memenuhi persyaratan ini (S6.6.2.3 dirujuk dari UNECE46):
S5.5.3 Waktu respons. Gambar pandangan belakang yang memenuhi persyaratan S5.5.1 (Bidang pandang) dan S5.5.2 (Ukuran), saat diuji sesuai dengan S14.2, ditampilkan dalam waktu 2,0 detik setelah dimulainya peristiwa mundur.
S5.5.4 Waktu tunggu. Gambar pandangan belakang yang memenuhi persyaratan S5.5.1 dan S5.5.2 tidak ditampilkan setelah acara mundur berakhir.
S5.5.5 Penonaktifan. Gambar pandangan belakang yang memenuhi persyaratan S5.5.1 dan S5.5.2 tetap terlihat selama peristiwa mundur hingga pengemudi mengubah tampilan, atau pemilih arah kendaraan berpindah dari posisi mundur.
S6.6.2.3.3.5 Artefak. Panduan operator harus merujuk pada kemungkinan artefak dan dampaknya pada oklusi parsial bidang pandang dan objek, yang mungkin mengharuskan pengemudi untuk lebih waspada dan memperhatikan.
S6.2.2.3.4.1 Kecepatan frame. Pergerakan objek di depan kamera dirender dengan lancar dan mulus. Kecepatan frame minimum sistem adalah setidaknya 30 Hz (setara dengan 30 fps). Dalam kondisi cahaya redup atau saat bermanuver dengan kecepatan rendah, kecepatan frame minimum sistem adalah minimal 15 Hz.
S6.2.2.3.4.2 Waktu pembentukan gambar. Waktu pembentukan gambar monitor adalah kurang dari 55 md pada suhu 22 derajat dalam Celsius ± 5 derajat dalam Celsius.
S6.2.2.3.4.3 Latensi sistem. Sistem monitor kamera (CMS) memiliki latensi yang cukup singkat untuk merender pemandangan hampir pada saat yang sama. Latensi lebih rendah dari 200 md pada suhu 22 derajat Celsius ± 5 derajat Celsius.
Kami memperkenalkan Sistem Tampilan yang Diperluas (EVS) Android Automotive OS (AAOS) untuk mematuhi persyaratan ini di AAOS bare metal. Kami memperkenalkan layanan serupa untuk Virtualisasi di perangkat AAOS dengan perender ketersediaan tinggi (HAR), yang juga menunjukkan kepatuhan terhadap persyaratan ini.
Pipeline pratinjau kamera
Lima tahap ini membentuk pipeline pratinjau kamera:
Gambar 1. Tahapan pipeline pratinjau kamera.
Blokir layanan kamera mengacu pada platform Layanan Kamera dan lapisan abstraksinya yang memungkinkan aplikasi mengakses dan menggunakan kamera yang tersedia. Fungsi Display Service memvisualisasikan data gambar untuk pengguna. Aplikasi mengimplementasikan perjalanan pengguna target dengan Layanan Kamera dan Layanan Tampilan.
Perjalanan pengguna visibilitas belakang utama adalah:
Pengemudi menempatkan pemilih arah (gigi) di posisi Mundur untuk memicu peristiwa mundur.
Sistem menyiarkan peristiwa pendukung. Aplikasi menerima siaran dan menginisialisasi blok input kamera (Layanan Kamera) dan perender (Layanan Tampilan).
Blok input kamera menginisialisasi platform Layanan Kamera dan menampilkan handle layanan ke aplikasi.
Renderer menginisialisasi jendela tampilan untuk input kamera dari langkah 4.
Aplikasi meminta blok input kamera untuk mulai mengirimkan buffer frame dan peristiwa.
Aplikasi mengantrekan buffer frame yang dikirim melalui callback (asinkron). Buffer frame dimiliki oleh blok input kamera, sehingga aplikasi tidak dapat memodifikasinya.
Aplikasi mengeluarkan buffer frame dari antrean (jika antrean tidak kosong) dan menyusun tampilan pengguna. Pengguna dapat membuat salinan untuk mengubah isinya.
Aplikasi mengirimkan buffer ke perender.
Perender menggambar konten buffer yang diterima di layar.
Jika peristiwa pendukung tetap dalam proses, lanjutkan ke Langkah 7. Saat peristiwa pendukung selesai, aplikasi meminta blok input kamera untuk berhenti mengirimkan buffer frame dan peristiwa setelah menyembunyikan tampilan dari pengguna.
Aplikasi secara opsional menutup kamera dan melepaskan perender.
Gambar 1 mengilustrasikan alurnya. Gambar ini menggunakan elemen dari QNX Camera Library API untuk menggunakan platform Layanan Kamera.
Gambar 2. Perjalanan pengguna utama HAR.
Blok input kamera mendeklarasikan tiga antarmuka:
CameraManager, mendeklarasikan metode untuk mengelola perangkat kamera; misalnya, aplikasi menggunakan antarmuka ini untuk membuka (mencadangkan) perangkat kamera target.CameraDevicemendeklarasikan metode untuk mengontrol perangkat kamera; misalnya, memulai atau menghentikan aliran data.CameraStreamListenermendeklarasikan satu metode untuk menerima berbagai peristiwa dari kamera target.
Desain
Bagian ini menjelaskan desain sistem.
Pengalaman pengguna
Pengemudi dapat melihat pratinjau kamera belakang di layar cluster instrumen saat memasukkan gigi mundur. Layar berhenti menampilkan pratinjau kamera saat pengemudi memindahkan tuas persneling dari gigi mundur.
Perjalanan pengguna tambahan dapat diaktifkan. Misalnya, pengemudi dapat melihat pratinjau area yang tidak terlihat di kaca spion saat lampu sein diaktifkan.
Mulai pratinjau kamera
Saat menggunakan kamera, aplikasi mencantumkan dan mengevaluasi kamera yang tersedia untuk menemukan kamera terbaik untuk tujuan yang dimaksud. Misalnya, untuk visibilitas belakang, aplikasi mencari kamera yang menampilkan sisi belakang kendaraan dari daftar kamera yang tersedia.
Aplikasi mengevaluasi hal ini dengan memeriksa karakteristik setiap kamera, misalnya, lokasi, arah lensa, kecepatan frame, resolusi output, dan format output. Jika beberapa kamera memiliki karakteristik wajib yang sama, aplikasi mungkin memeriksa karakteristik tambahan, seperti bidang tampilan dan jarak fokus.
Gambar ini menunjukkan urutan untuk memulai pratinjau kamera dengan konfigurasi kamera statis:
Gambar 3. Mulai pratinjau kamera dengan konfigurasi kamera statis.
Menghentikan pratinjau kamera
Aplikasi berhenti memberikan visibilitas belakang saat acara mundur berakhir. Untuk menghindari menampilkan layar kosong atau gambar diam, aplikasi menyembunyikan tampilan dari pengguna terlebih dahulu, lalu meminta agar blok input kamera berhenti mengirim peristiwa.
Gambar ini menunjukkan urutan untuk menghentikan aliran data dari perangkat kamera target:
Gambar 4. Menghentikan aliran data dari perangkat kamera target.
Error
Perangkat kamera dapat berhenti mengirim buffer frame baru secara tiba-tiba. Untuk mendeteksi insiden tersebut, blok input kamera dapat menerapkan timer yang berakhir saat frame baru tiba dan mengirim notifikasi saat timer ini berakhir.
Saat menerima notifikasi, aplikasi akan memberi tahu pengguna bahwa pratinjau kamera tidak lagi live dan mencoba memulihkan pratinjau kamera dengan menutup perangkat kamera dan membukanya lagi. Gambar 5 menunjukkan cara aplikasi menangani waktu tunggu:
Gambar 5. Menangani waktu tunggu habis (aliran data terhenti).
Blok input kamera dapat melaporkan insiden selain aliran data yang terhenti dan menyematkan lebih banyak detail dalam buffer. OEM dapat menggunakan metadata peristiwa ini untuk menangani insiden di platform mereka.
Aktivitas
API ini digunakan oleh aplikasi yang berjalan di host dan mengelola tampilan panel instrumen melalui HAR (blok biru dalam diagram di bawah).
Diagram sistem diilustrasikan pada Gambar 5:
Gambar 6. Diagram sistem.
Layanan
Panggilan API diharapkan berjalan dalam konteks proses panggilan.
API
API baru ini hanya ditujukan untuk aplikasi yang mengelola pratinjau kamera di layar cluster instrumen melalui HAR. API tersedia melalui lapisan abstraksi platform dan ditautkan secara dinamis.
Antarmuka CameraInputBlock mendeklarasikan metode untuk menginisialisasi fungsi kamera dan mendapatkan pengelola blok input. Aplikasi menggunakan instance
CameraManager yang ditampilkan untuk mengelola perangkat kamera.
// This class represents a camera input block for the application that manages the
// instrument cluster display with Harry.
public class CameraInputBlock : public InputBlock {
public:
// Clean up the resources.
virtual ~CameraInputBlock();
// A method inherited from InputBlock class. This method initializes
// CameraInputBlock instance; e.g. checking the platform camera service
// is live.
//
// @return CAMERA_EPERM if the platform camera service is not
// available.
// CAMERA_OK otherwise.
virtual CameraError init() override;
// A method inherited from InputBlock class. This method release all
// resources held by this CameraInputBlock instance.
virtual void release() override;
// This method returns a CameraManager instance. The caller uses
// this instance to manage camera devices.
//
// @param out If this method is successful, this points to a valid
// CameraManager instance.
// @return CAMERA_EACCESS when we fail to create CameraManager instance
// to return.
// CAMERA_OK otherwise.
virtual CameraError getCameraManager(
std::shared_ptr<CameraManager>* out) = 0;
private:
// Handle to manage camera devices.
std::shared_ptr<CameraManager> mMgr;
// Handle to manage camera devices that have been opened by clients.
std::set<CameraDevice> mCameras;
};
Class CameraManager mendeklarasikan metode untuk membuka (atau memiliki) kamera dan melepaskannya saat aplikasi selesai menggunakan kamera tersebut. Aplikasi dapat membuka lebih dari satu
kamera dan menggunakan streaming-nya untuk menciptakan pengalaman multi-tampilan atau
bidang pandang yang lebih luas.
// This pure virtual class declares methods to manage camera devices.
public class CameraManager {
public:
// This method returns a list of CameraDescriptor objects representing
// available cameras.
//
// @param out A list of CameraDescriptor instances. This list may be
// empty if the platform camera service does not list any
// camera.
// @return CAMERA_EACCESS if we failed to build a camera list.
// CAMERA_OK otherwise.
virtual CameraError getCameraList(
std::vector<CameraDescriptor>* out) = 0;
// Open a camera device associated with a given string identifier.
//
// @param ID A string identifier of a camera device to request.
// @param out A pointer to CameraDevice shared pointer object. This
// is null when we fail to open a target device.
// @return CAMERA_ENODEV if no camera is associated with a given id.
// CAMERA_EACCESS if it fails to open a target device.
// CAMERA_OK otherwise.
virtual CameraError open(
std::string ID, std::shared_ptr<CameraDevice>* out) = 0;
// Close a camera device associated with a given string identifier.
// This method is assumed to be always successful.
//
// @param id A string identifier of a camera device to close.
virtual void close(std::string id) = 0;
};
Jika aplikasi tidak dapat mendeteksi kamera mana yang akan digunakan, aplikasi dapat memilih kamera yang berfungsi paling baik dalam konteks tersebut. CameraManager::getCameraList() menampilkan daftar instance
CameraDescriptor, yang memberikan karakteristik setiap kamera.
Class CameraDevice mewakili satu perangkat kamera dan mendeklarasikan metode
untuk memulai dan menghentikan aliran datanya. Jika karakteristik kamera tidak diketahui secara statis, klien akan mendapatkannya dari deskriptor dan menguraikannya.
Misalnya, klien dapat mendapatkan daftar konfigurasi streaming yang ditawarkan oleh perangkat kamera target dari metadatanya dan memilih konfigurasi dengan atribut terbaik (misalnya, kecepatan frame, resolusi, dan format output).
// This class represents a single camera device.
public class CameraDevice {
public:
// Start a data stream that attributes are matching to given
// configuration best.
// If a selected configuration is not given (null), a data stream is
// initiated in its default configuration and return.
//
// @param configuration Selected attributes of the imagery data stream.
// @param listener An object to listen to an active data stream.
// @param effective Actual attributes of started data stream.
// @return CAMERA_EINVAL if a listener object is invalid.
// CAMERA_EIO if we failed to start a video stream.
// CAMERA_OK otherwise.
virtual CameraError start(
std::shared_ptr<CameraStreamConfiguration>& configuration,
std::shared_ptr<CameraStreamListener>& listener,
std::shared_ptr<CameraStreamConfiguration>* effective) = 0;
// Stop a data stream.
virtual void stop() = 0;
// Get a camera descriptor.
//
// @param desc A set of attributes that defines this camera device.
// @return CAMERA_ENODATA if a descriptor is not available.
// CAMERA_OK otherwise.
CameraError getDescriptor(std::shared_ptr<CameraDescriptor>* desc) = 0;
// Return a consumed buffer to the camera device. A client of active
// stream must return a frame buffer explicitly by calling this method.
virtual void doneWithFrame(std::shared_ptr<FrameBuffer>& buffer) = 0;
private:
// Describe this camera device.
CameraDescriptor mDescriptor;
// A weak reference to a listening client.
std::weak_ptr<CameraStreamListener> mClient;
};
// This class declares attributes that characterize a camera device.
public class CameraDescriptor {
public:
// Unique std::string object to identify a single camera device.
std::string mId;
// A set of stream configurations this camera device is capable of. A
// camera must have at least one stream configuration.
std::set<CameraStreamConfiguration> mConfigurations;
// Are more attributes needed to exist, such as locations, lens
// facing directions, and intrinsic/extrinsic parameters?
};
// This class declares attributes that characterize an imagery data stream.
public class CameraStreamConfiguration {
public:
// Width of output of this stream in pixels.
unsigned int mWidthInPixels;
// Height of output of this stream in pixels.
unsigned int mHeightInPixels;
// An average number of frames per second.
double mFrameRate;
// A format of this stream's output. A client could calculate a
// byte-per-pixel (bpp) from this.
CameraColorFormat mFormat;
};
// This class represents a listener/callback object to listen to frames and
// events.
public class CameraStreamListener {
public:
// A listener method to receive various stream events including a new
// frame buffer.
//
// @param event CameraStreamEvent object that represents a single event
// such as an arrival of a new frame buffer, camera stream
// is terminated, and so forth.
virtual void onEvent(std::shared_ptr<CameraStreamEvent>* event) = 0;
};
CameraDevice::start() menggunakan tiga argumen:
Konfigurasi streaming yang dipilih oleh pemanggil.
Pemroses untuk menerima peristiwa streaming.
Pointer ke konfigurasi streaming yang efektif. Sebaiknya pemanggil memeriksa nilai ini untuk menangani buffer frame yang akan datang sesuai yang diinginkan.
Saat memulai aliran data dengan platform Layanan Kamera, CameraDevice::start() menyimpan referensi lemah ke objek pemroses panggilan untuk mendeteksi penghentian panggilan yang tidak terduga.
Saat klien selesai menggunakan buffer frame, klien harus memberi tahu perangkat kamera
bahwa klien tidak lagi memerlukan buffer frame dengan memanggil
metode CameraDevice::doneWithFrame().
Saat streaming dimulai, klien akan menerima pesan peristiwa. Pesan umum adalah buffer frame baru. Melalui fungsi callback terdaftar, klien menerima peristiwa
kNewFrameBuffer yang berisi data gambar beserta metadata buffer
frame. StreamEventType mendeklarasikan lebih banyak jenis untuk menangani peristiwa
streaming lainnya. Seperti aliran data yang berhenti atau terhenti.
// This class lists events possibly occurring while a data stream is active.
enum class CameraStreamEventType {
// A delivery of a new frame buffer.
kNewFrameBuffer,
// A data stream has been stopped.
kStreamStopped,
// No new frame buffer arrives for a while.
kStreamHang,
// Add more.
...
};
// This class represents a single instance of StreamEventType.
public class CameraStreamEvent {
public:
// Return a type of this event.
//
// @return CameraStreamEventType enum value.
CameraStreamEventType getType() { return mType; }
// Return a pointer to data associated with this event.
//
// @return A shared pointer object of the buffer that contains data for
// this event.
std::shared_ptr<void> getData() { return mData; }
private:
// Describe a type of this event.
CameraStreamEventType mType;
// A pointer to the data buffer.
std::shared_ptr<void> mData;
};
// This class inherits StreamEvent class and has additional fields to represent
// the frame buffer.
public class FrameBufferEvent : public CameraStreamEvent {
public:
// Return an identifier of this frame buffer.
//
// @return A unique integer value to identify this frame buffer.
int getBufferID() { return mBufferID; }
// Give access to frame buffer metadata.
//
// @return A shared pointer to the buffer that contains data besides
// the imagery data.
std::shared_ptr<void> getMetadata() { return mMetadata; }
private:
// Unique integer to identify this buffer.
int mBufferID;
// A pointer to metadata of this frame buffer.
std::shared_ptr<void> mMetadata;
};
Contoh ini menunjukkan penerapan antarmuka CameraInputBlock dan
aplikasinya:
CameraError getCameraManager(std::shared_ptr<CameraManager>* out) {
// During an instantiation, CameraManager will retrieve a list of camera
// devices from the platform camera service and identify their attributes.
*out = std::make_shared<CameraManager>();
return CAMERA_OK;
}
// This method returns a list of CameraDescriptor objects representing available
// cameras.
CameraError CameraManager::getCameraList(std::vector<CameraDescriptor>* out) {
if (mCameraList.size() < 1) {
// Query a list of cameras and get their attributes.
}
*out = mCameraList;
return CAMERA_OK;
}
// Open a camera device associated with a given string identifier.
CameraError CameraManager::open(std::string id, std::shared_ptr<CameraDevice>* out) {
if (!mCameraList.contains(id)) {
// We cannot identify any camera with a given value.
return CAMERA_NODEV;
}
// During a construction, CameraDevice will obtain a handle of a target
// camera device from the platform camera service.
std::shared_ptr<CameraDevice> h = std::make_shared<CameraDevice>(id);
if (!h) {
// We fail to open a camera device.
return CAMERA_EACCESS;
}
*out = h;
return CAMERA_OK;
}
// Close a camera device associated with a given string identifier. This method
// is assumed to be always successful.
void CameraManager::close(std::string id) {
if (!mCameraList.contains(id)) {
// We ignore calls with unknown identifiers.
return;
}
// mCameraList.remove() returns an object removed from the list.
std::shared_ptr<CameraDevice> device = mCameraList.remove(id);
// Ensure a device stops streaming.
device->stop();
}
// Start a data stream that attributes are matching to given configuration
// best.
// If a selected configuration is not given (null), a data stream will be
// initiated in its default configuration and return.
CameraError CameraDevice::start(
std::shared_ptr<CameraStreamConfiguration>& configuration,
std::shared_ptr<CameraStreamListener>& listener,
std::shared_ptr<CameraStreamConfiguration>* effective) {
if (!listener) {
return CAMERA_EINVAL;
}
// selectStreamConfiguration examines this camera's stream configurations
// and returns the one closest to the selected configuration.
CameraStreamConfiguration config = selectStreamConfiguration(configuration);
// mDevice refers to the camera handle for the platform camera service. We
// may need to translate CameraStreamConfiguration for the platform service.
mDevice->configure(
configuration.mWidth, configuration.mHeight, configuration.mFormat);
// Start a data stream with a callback object.
if (!mDevice->startStream(mCallback)) {
// We failed to start a data stream.
return CAMERA_EIO;
}
return CAMERA_OK;
}
// Stop a data stream.
void CameraDevice::stop() {
if (!mDevice) {
// Nothing to do if we don't have a valid camera handle for the
// platform camera service.
return;
}
mDevice->stopStream();
}
// Get a camera descriptor.
CameraError CameraDevice::getDescriptor(std::shared_ptr<CameraDescriptor>* desc) {
if (!mDescriptor) {
return CAMERA_ENODATA;
}
*desc = *mDescriptor;
return CAMERA_OK;
}
// Return a consumed buffer to the camera device. A client of active stream
// must return a frame buffer explicitly by calling this method.
void CameraDevice::doneWithFrame(std::shared_ptr<FrameBuffer>& buffer) {
if (!mBufferRecords.contains(buffer.getId())) {
// Ignore a call with unknown frame buffer.
return;
}
// Simply remove from the record.
(void)mBufferRecords.remove(buffer.getId());
}
// This method handles gear-shift events.
void Application::handleGearShift(GearSelection selection) {
switch (selection) {
case GEAR_SELECTION_REVERSE:
// Upon the reverse gear selection, we are going to start a video
// stream and show its preview on the instrument cluster display.
(void)startStream(mCameraInputBlock);
// FIXME: Exact method to control the camera preview window on the
// instrument display is to be determined.
show(mRearVisibilityWindow);
break;
default:
// Upon all other gear selection, we are going to stop a video
// stream (if it's running) and hide the preview.
stopStream(mCameraInputBlock);
// FIXME: Exact method to control the camera preview window on the
// instrument display is to be determined.
hide(mRearVisibilityWindow);
break;
}
}
bool Application::startStream(std::shared_ptr<CameraInputBlock> handle) {
return handle->start(std::bind(&Application::handleStreamCallback, this);
}
void Application::stopStream(std::shared_ptr<CameraInputBlock> handle) {
handle->stop();
}
// This method handles a stream callback.
void Application::handleStreamCallback(StreamEvent& event) {
switch (event.getType()) {
case StreamEventType::kNewFrameBuffer:
// Handle a new frame buffer. We may just enqueue it for the
// future or forward to CameraInputBlock client.
break;
case StreamEventType::kStreamStopped:
// Handle as an incident if this event is not expected.
break;
// More cases to be added.
}
}
void Application::handleNewFrameBuffer(StreamEvent& event) {
// Enqueue a new frame buffer for the further processing. A buffer
// must be returned explicitly by calling
// CameraDevice.doneWithFrame(FrameBuffer&) method.
}
void Application::handleStreamEvent(StreamEvent& event) {
// Handle a received stream event except a new frame buffer's
// arrival; e.g. a video stream is terminated unexpectedly.
}
Performa
Visibilitas belakang memenuhi peraturan pemerintah ini.
| Nilai | Peraturan |
|---|---|
| Waktu respons | CFR 571.111 S5.5.3 |
| Kecepatan frame | UNECE R46 6.2.2.3.4 |
| Waktu pembentukan gambar | UNECE R46 6.2.2.3.4.2 |
| Latensi sistem | UNECE R46 6.2.2.3.4.3 |
Privasi
Khusus untuk privasi:
API tidak mewajibkan penerapan untuk mengumpulkan, mencatat, atau menyimpan informasi identitas pribadi (PII). Namun, karena data gambar yang diambil (atau metadata terkait) dapat berisi PII, aplikasi yang menggunakan API harus mendapatkan izin eksplisit pengguna.
Pengguna tidak dapat mengontrol perangkat kamera untuk melihat pratinjau di layar panel instrumen karena kamera terlibat dalam peran penting untuk keselamatan. OEM mendapatkan izin pengguna selama penyiapan atau dari pengemudi.
API ini tidak mendukung klien kamera latar belakang. Oleh karena itu, indikator privasi, yang memberi tahu pengguna bahwa perangkat kamera sedang merekam data, berada di luar cakupan.